How to get C1 CMS username of current logged in user, not the windows user - c1-cms

I'm trying to filter records from a C1 CMS data folder in the Console as part of a staff profile system on my website. What I'd like to do is show a single profile record for the staff member who is logged into the C1 Console, so that they can only edit their own staff profile and nobody else's. To do this, I'd like to match up the username they logged in with with a field in the data folder for the profiles.
So far I've created the datatype BaileyWeb.University.People, some sample records, and have added tree file:
<?xml version="1.0" encoding="UTF-8"?>
<ElementStructure xmlns="http://www.composite.net/ns/management/trees/treemarkup/1.0" xmlns:f="http://www.composite.net/ns/function/1.0">
<ElementStructure.AutoAttachments>
<NamedParent Name="Content" Position="Bottom"/>
</ElementStructure.AutoAttachments>
<ElementRoot>
<Children>
<Element Label="My Profile Function" Id="MyProfileRoot" Icon="user-group">
<Children>
<DataElements Type="BaileyWeb.University.People" Label="${C1:Data:BaileyWeb.University.People:DisplayName}" Icon="user">
<Actions>
<EditDataAction Label="Edit My Profile" />
<DeleteDataAction Label="Delete My Profile" />
</Actions>
<Filters>
<FunctionFilter>
<f:function name="BaileyWeb.University.Data.MyProfile.MyFilter" xmlns:f="http://www.composite.net/ns/function/1.0" />
</FunctionFilter>
</Filters>
</DataElements>
</Children>
</Element>
</Children>
</ElementRoot>
</ElementStructure>
In my C# function, I do the filtering, as per the documentation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
namespace BaileyWeb.University.Data
{
public class MyProfile
{
public static Expression<Func<BaileyWeb.University.People, bool>> MyFilter()
{
Expression<Func<BaileyWeb.University.People, bool>> filter = f => f.UserId.Contains(System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString());
return filter;
}
}
}
Unfortunately, this doesn't work, and I'm not sure why.
I'm NOT using the Active Directory login add-on, so domain logins aren't being used here. I've tried swapping out System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString() for a simple string of "admin" (which is used as a UserID for one record in the datatype) to test it, but this also fails to return a result.
When I went back to the basic tree filtering:
<Filters>
<ParentIdFilter ParentType="BaileyWeb.University.People" ReferenceFieldName="UserId" />
<FieldFilter FieldName="UserId" FieldValue="admin"/>
</Filters>
... I got a result displayed, but this was for a static username value of "admin".
Can anyone help me solve this problem?

Did you ask for logged C1 username?
Composite.C1Console.Security.UserValidationFacade.GetUsername()

Related

Easy way to implement splash screen in React Native application

I am new to React-Native development. I try to implement a splash screen in my app. I tried a lot of options from the web but not get success because some of the code is outdated and some process is very confusing.
Use react-native-splash-screen Sample code is below
import SplashScreen from 'react-native-splash-screen'
export default class WelcomePage extends Component {
componentDidMount() {
// do stuff while splash screen is shown
// After having done stuff (such as async tasks) hide the splash screen
SplashScreen.hide();
}
}
To learn more see examples
To make full screen
On MainActivity.java, just like that:
#Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this, R.style.SplashTheme); // Add theme here
super.onCreate(savedInstanceState);
}
IN res/values/styles.xml
<resources>
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>
</resources>
launch_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="#drawable/launch_screen" android:scaleType="centerCrop" />
</RelativeLayout>
I recommend react-native-bootsplash since it's still actively maintained.
Before implementing any library that asks you to add code to the Swift and Java bridge files it's a good idea to familiarize yourself with the RN folder structure. Once you understand the folder structure and some of the main files it becomes much easier to debug your app and you will be able to develop apps faster.

ADB2C Custom policy user journey - override the content definition of each orchestration step

I have a custom policy which I am setting up which is based 2 steps in the user journey
Sign in signup unified
Self assert page.
In my RP file, I have specified ContentDefinitions for each 'type' of page so I can override these with my own. From my understanding, as the RP file is the last one point in the hierarchy, it will override always.
What I am finding is that it works for step 1, but step 2 always seems to default to the standard Microsoft page.
e.g. RP file.
<ContentDefinitions>
<!--For step 1-->
<ContentDefinition Id="api.signuporsignin">
<LoadUri>https://MYURL/custom_step1.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:1.2.0</DataUri>
<Metadata>
<Item Key="DisplayName">Signin</Item>
</Metadata>
</ContentDefinition>
<!--For step 2-->
<ContentDefinition Id="api.selfasserted">
<LoadUri>https://MYURL/custom_step2.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:1.2.0</DataUri>
<Metadata>
<Item Key="DisplayName">Collect information from user page</Item>
</Metadata>
</ContentDefinition>
</ContentDefinitions>
Ive seen on my UserJourney that Step 1 also seems to define a ContentDefinition (a default I guess?) but specifying my own one on each step didn't seem to have any effect either.
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
Suggestions appreciated!

Is it possible to create an integration cartridge for BM in the Saleforce for "Marchant Tools" using controllers, not pipelines?

I must create new cartridge for integration in BM but I don't want use pipelines. Can I use the controllers for this? If yes, please provide information on how to do this.
.
Yes, you can. You need to create the bm_extensions.xml and add all the actions/entries.
Note: The file mention pipeline but It can actually be a Controller as you can see in the example I linked below.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<extensions xmlns="http://www.demandware.com/xml/bmmodules/2007-12-11"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.demandware.com/xml/bmmodules/2007-12-11 bmext.xsd">
<menuaction id="paypal_transactions_manager" menupath="orders" position="200" site="true">
<name xml:lang="x-default">PayPal Transactions</name>
<short_description xml:lang="x-default">Manage the PayPal transactions related with this site orders.</short_description>
<description xml:lang="x-default">Manage the PayPal transactions related with this site orders.</description>
<exec pipeline="PaypalAdmin" node="Orders" />
<sub-pipelines>
<pipeline name="PaypalAdmin-Orders" />
<pipeline name="PaypalAdmin-OrderTransaction" />
<pipeline name="PaypalAdmin-Action" />
<pipeline name="PaypalAdmin-CreateNewTransaction" />
</sub-pipelines>
<icon>paypalbm/images/icon_transactions.png</icon>
</menuaction>
</extensions>
PayPal Cartridge bm_paypal is a good example to understand how is done: https://github.com/SalesforceCommerceCloud/link_paypal/tree/master/cartridges/bm_paypal/cartridge
Ps: Let me know if you cannot access the link.

Spring Security 3.1 ActiveDirectoryLdapAuthenticationProvider returning partial result exception

I am trying to authenticate users to an Active Directory Instance using spring security, I am getting an Partial Results Exception. I am going around in circles trying to figure this out. Below is my config.
security-app-context
<authentication-manager erase-credentials="true">
<authentication-provider>
<user-service>
<user name="admin#damien.com" authorities="ROLE_ADMINISTRATOR" password="123admin123" />
</user-service>
</authentication-provider>
<authentication-provider ref="ldapActiveDirectoryAuthProvider"/>
</authentication-manager>
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="myDomain.com" />
<constructor-arg value="ldap://ldapurl:389/" />
<property name="convertSubErrorCodesToExceptions" value="true"/>
</bean>
Error I am getting
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 0 org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntryInternal(SpringSecurityLdapTemplate.java:239)
I am struggling to find examples and the documentation indicates I am working in the right direction.
This is from the logs
SpringSecurityLdapTemplate.java 213 - Searching for entry under DN '', base = 'dc=myDomain,dc=com', filter = '(&(objectClass=user)(userPrincipalName={0}))'
and this is what I would expect that to look like on a successful attempt from some scripts that work
Searching for entry under DN 'OU=Users and Groups,DC=one,DC=two,DC=myDomain,DC=com', base = 'OU=Users and Groups,DC=one,DC=two,DC=myDomain,DC=com', filter = '(&(objectClass=user)(userPrincipalName={0}))'
Do I need to get the DN populated? How? I have looked through the ActiveDirectoryLdapAuthenticationProvider properties and don't see a way? Also the base is off but myDomain.com is the correct domain for users e.g john.doe#myDomain.com. Has anyone come across a similar problem?
To solve this I used the default LDAP provider which enables user search base to be specified, specifying the user search base and user search filter.
<ldap-authentication-provider
user-search-base="OU=Users and Groups,DC=abc,DC=myDomain,DC=com"
user-search-filter="userPrincipalName={0}" />
A user would then be logging in with john.doe#myDomain.com but the usersearch base is more specific(abc.myDomain.com). I believe AD Spring was falling down due to this.

Security using the Membership provider that will support Active Directory and your own bespoke provider

I have a task of dealing with security on my .Net web application, the way it is to work is that if the user is logged in to Active Directory and the users AD name is in a database then they will be let in.
On the same bases if the users AD name is not in the database then they will be asked to login, with a user name and password, held in the database.
So I need some kind of mix mode security login using the Membership and Role provider.
Where I am having trouble is where do you detect if a user can login using AD, so they get logged in automatically.
Sounds like you'll need to implement a custom MembershipProvider that inherits from ActiveDirectoryMembershipProvider.
At a minimum, you'll need to override ValidateUser so that if the base.ValidateUser returns false, you can attempt to validate the user in your SQL database. The following code sample works in my test application, however I did not implement the SQL method. That should be pretty straight forward for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Configuration;
using System.Configuration.Provider;
namespace Research.Web.Security
{
public class MixedMembershipProvider : ActiveDirectoryMembershipProvider
{
protected String SqlConnectionString { get; private set; }
private String GetConnectionString(String connectionStringName)
{
if (string.IsNullOrEmpty(connectionStringName))
throw new ProviderException("ConnectionStringName must be specified.");
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
{
throw new ProviderException(String.Format("Connection string {0} not found.", connectionStringName));
}
return settings.ConnectionString;
}
public override void Initialize(String name, System.Collections.Specialized.NameValueCollection config)
{
this.SqlConnectionString = GetConnectionString(config["sqlConnectionStringName"]);
config.Remove("sqlConnectionStringName");
base.Initialize(name, config);
}
public override Boolean ValidateUser(String username, String password)
{
if (!base.ValidateUser(username, password)) // validate using AD first
{
return ValidateUserSql(username, password); // if not in AD, check SQL
}
else
{
return true;
}
}
private Boolean ValidateUserSql(String username, String password)
{
// look up your account in SQL here
return true;
}
}
}
Your web config would look something like this:
<configuration>
<!-- usual config stuff omitted -->
<connectionStrings>
<add name="SqlDefault" connectionString="Server=localhost;database=mydatabase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
<add name="ActiveDirectoryDefault" connectionString="LDAP://mydomain.com/DC=mydomain,DC=com" />
</connectionStrings>
<system.web>
<!-- usual config stuff omitted -->
<membership defaultProvider="Mixed">
<providers>
<clear/>
<add name="Mixed"
type="Research.Web.Security.MixedMembershipProvider, Research.Web"
applicationName="/"
connectionStringName="ActiveDirectoryDefault"
sqlConnectionStringName="SqlDefault"
connectionUsername="mydomain\myadmin"
connectionPassword="mypass"/>
</providers>
</membership>
<!--- usual config stuff omitted -->
</system.web>
</configuration>
The above code will work for basic authentication, but you may need to override some of the other methods to handle password resets, lookups, etc. for the eventuality that an account is in SQL and not AD.

Resources