Pre-condition not working - vdm++

I'm trying to create a simple 'signup' method.
-- Creates a new account
public signup: String * String ==> ()
signup(username, password) == (
-- create user
dcl user: User := new User(username, password);
-- add user
users := users union {user};
)
pre (let u in set users in u.username <> username);
The problem I'm having is with the pre-condition. How can I write the pre-condition 'username is unique'? (ie there is no user in users where user.username = username)
Note: users is a set of User
Edit: pre (username not in set users.username) is what makes most sense to me, but this doesn't even compile.

It looks like you need a "forall". Your precondition wants to say that "for all of the users' usernames, the new user's name is not equal to them". An alternative would be to generate the set of existing usernames with a set comprehension, and then say the new username is not in that set.
Let us know if the syntax for the above isn't obvious.

Related

Is it possible to add a role to a user with alanning:roles in meteor from an template event?

I am fairly new to Meteor and have been having real trouble with this issue.
I would like to have a select element which updates the users role (once logged in) depending on the option selected. I'm storing the value of the option as a variable when the select is changed and trying to take this value as the name of the role to add to the user.
When I run my app and change the select, the role seems to pop up for a second (viewed in Mongol) before disappearing again. I created a small test to display an alert of the role for the user, which shows up containing the name of the role but once you OK it, the role has disappeared. Am I missing something here?
Here is my template containing the select element...
<template name="select">
<select id="select">
<option value="working">Looking for work</option>
<option value="hiring">Hiring</option>
</select>
</template>
And here is the client side code for the change event
Template.select.events({
'change #select': function (event) {
//remove any current roles added to the user as it will be either
//one or the other
Roles.removeUsersFromRoles( Meteor.userId(), 'working', 'hiring' );
//add a role to the current user with the value from select box
var value = $(event.target).val();
Roles.addUsersToRoles( Meteor.user(), value );
//each of these alerts displays correctly depending on the select
//value
var test = Roles.userIsInRole( Meteor.user(), 'hiring' ); // true
if (test===true){
alert('in hiring role');
}
var test2 = Roles.userIsInRole( Meteor.user(), 'working' ); // true
if (test2===true){
alert('in working role');
}
// either working or hiring
alert(Roles.getRolesForUser(Meteor.userId()));
// alert displays count of 1 when you select 'hiring'
alert(Roles.getUsersInRole('hiring').count());
}
});
Any help would be much appreciated, have been searching through the documentation and online for several days to no avail. Many thanks :)
You try to add roles in your client. However, the client reflects only the data from the server's Roles collection.
You need therefore to change your code to a server side method, that
a) checks wether the current user is permitted to change roles (warning here, potential security threats when not checking permissions)
b) checks, wether the targeted user exists
c) sets the roles for the given userId
There is a good example in the documentation on how to do that. This is a slightly modified version of it:
Meteor.methods({
'updateRoles'({userId, roles, group}) {
check(userId, String);
check(roles, [String]);
check(group, String);
// a) check permission
if (!this.userId || !Meteor.users.findOne(this.userId) || !Roles.userIsInRole(this.userId, 'update-roles', 'lifted-users'))
throw new Meteor.Error('403', 'forbidden', 'you have no permission to change roles');
// b) check target user
if (!Meteor.users.findOne(userId))
throw new Meteor.Error('404', 'user not found');
// c) update user's roles
Roles.setUserRoles(userId, roles, group);
return true;
}
});
This method assumes, that there is a special role/group combination for users, that are allowed to change roles. This should be only a very few people, like admins.
Also note, that this method sets the user roles by using Roles.setUserRoles. If you want to extend the roles you need to use Roles.addUserToRoles.
You can then call this method from your client like every Meteor method:
Template.select.events({
'change #select': function (event) {
// get value from select box
var roles = [$(event.target).val()];
// TODO create a second select for the group
var group = 'defaultUsers'
var userId = Meteor.userId();
Meteor.call('updateRoles', { userId, roles, group }, (err, res) => {
// handle err / res
console.log(Roles.userIsInRole(userId, roles, group)); // should return true
});
}
});
Note, that Roles on the client is a collection which is immediately subscribed to. Changes are reflected reactively. If you do not see the changes immediately

How to create a user with email as login using Graph API in Azure B2C

I am implementing Azure B2C in my ASP MVC application.
My sign up policy has email account chosen so If a user sign up, his account is created and he can log in using his email (I mean private email like xxx#gmail).
If I look at old azure portal -> users section, for this particular user there is no meaningfull data, just objectId. Where the email he provided is stored? (alternate mail field is empty).
And here starts my real question.
I would like also add users via Graph API. I am doing this via GraphConsoleAppV3 sample application. However I cannot set the mail field, the only thing I can do is add the email (custom email like #gmail) to the 'OtherEmails' collection.
But adding the user this way, I cannot log in to my application using private email. I can login using UPN name but I do not want to. Users will not know the UPN, only they real emails.
I can see in the Internet samples with something like 'SignInNames' but iin PowerShell.
I would like to set the user via Graph API and indicate that it has email as login type - not UPN. Hot to achieve it?
I have found that there is other sample project to create users in B2C (via posts with json). It seems that to sync B2C with AD and entire graph will take a while and all the nomenclature needs to unified
Not sure I understand the question, and this is from ages ago, but this may help someone in the future.
If you want to create a user in B2C through the Microsoft Graph API in C#, with an email as their sign-in, you can do the following:
NOTE: This is assuming you already setup the Microsoft Graph API in your C# application. If you have not done that yet, you can follow this.
First Create the user and the Identities.
public async Task CreateUser(string username, string givenName, string email, string password)
{
var identities = CreateIdentities(username, email, new List<ObjectIdentity>());
var user = new User
{
AccountEnabled = true,
DisplayName = username,
GivenName = givenName,
Identities = identities,
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = false,
Password = password
}
};
var response = await userRepository.CreateUserRequest(user);
}
When creating the Identities make sure the email and username are not the exact same values.
private List<ObjectIdentity> CreateIdentities(string username, string email, List<ObjectIdentity> identities)
{
if (email != null) identities = AddIdentity(identities, "emailAddress", email);
if (username != null && (!username.Equals(email) || email == null)) identities = AddIdentity(identities, "userName", username);
return identities;
}
/// <summary>
/// Adds an Identity to the ObjectIdentity list
/// </summary>
/// <param name="identities">List of identities</param>
/// <param name="signInType">Type of sign-in, which is mostly just emailAddress or userName</param>
/// <param name="issuerAssignedId">The value of the sign-in name or email, for example t.chermin#please.nl</param>
/// <returns>List of ObjectIdentity</returns>
private List<ObjectIdentity> AddIdentity(List<ObjectIdentity> identities, string signInType, string issuerAssignedId)
{
var identity = new ObjectIdentity
{
SignInType = signInType,
Issuer = issuer,
IssuerAssignedId = issuerAssignedId
};
identities.Add(identity);
return identities;
}
Finally, we can add the user to our AADB2C environment:
public async Task<User> CreateUserRequest(User user)
{
try
{
return await graphClient.Users
.Request()
.AddAsync(user);
}
catch (Exception ex)
{
}
return null;
}

Why does the Spring Social plugin occasionally return an empty email on the User class?

I have a Grails project (v2.4.2) that is making use of the spring-security-facebook:0.17 plugin to authenticate via Spring Security. At first sight, all seems well. However, there is a large set of users that for some unknown reason I cannot access their email address. I am using spring social to grab the email. I have permission and it is set in the scope. Here is a code snippet where I authenticate a new user:
log.info("Create domain for facebook user $token.uid")
//Use Spring Social Facebook to load details for current user from Facebook API
log.info("create: FacebookAuthToken: $token")
log.info("created FacebookAuthToken.FacebookAccessToken = ${token.accessToken}")
Facebook facebook = new FacebookTemplate(token.accessToken.accessToken)
org.springframework.social.facebook.api.User fbProfile = facebook.userOperations().getUserProfile()
// Check if email is actual granted because in production some are coming back null
boolean isEmailGranted=false
List<Permission> permissions = facebook?.userOperations()?.getUserPermissions()
String permissionString = "["
for (int i=0;i<permissions.size();i++) {
permissionString += "["+ permissions[i].getName() + ":" + permissions[i].getStatus()+"]"
if (permissions[i].getName()=="email" && permissions[i].isGranted())
isEmailGranted=true
}
permissionString += "]"
log.info("create: Facebook Permissions = " + permissionString)
def grailsWebRequest = WebUtils.retrieveGrailsWebRequest()
def flash = grailsWebRequest.flashScope
if (!isEmailGranted) {
log.warn("create: Unable to subscribe facebook user because email priviledge was not granted.")
flash.message = 'Login to Facebook failed. We must have access to your email address in order to proceed with login.'
throw new InsufficientAuthenticationException("Facebook email not accessible")
}
log.info("created: ")
String email = fbProfile.getEmail()
String firstName = fbProfile.getFirstName()
String lastName = fbProfile.getLastName()
String fullName = fbProfile.getName()
String username = firstName
String password = token.accessToken.accessToken
if (!email) {
log.error("create: Permission was granted to use facebook email but the value is null.")
flash.message = 'Login to Facebook failed. We are temporarily unable to access your email although permission has been granted'
throw new InsufficientAuthenticationException("Facebook email not accessible for unknown reason")
}
Why would I receive an empty email when permission has been granted? Is there a preferred method for handling this behavior (other than failing the authentication and making up a fake email address). Many thanks!
The documentation for the 'email' field of the 'user' object ( https://developers.facebook.com/docs/reference/api/user/ ) clarifies the expected behaviour here, which is:
"this field will not be returned if no valid email address is available"
There is a detailed explanation about different situations where an email won't be sent. Please check it out:
https://developers.facebook.com/bugs/298946933534016/
I hope it helps.

Use default credentials in order to call DirectoryEntry

I am working in a Login page and teh logic is like ->
try
{
DirectoryEntry LDAPLogin = new DirectoryEntry(ConfigurationSettings.AppSettings ["LDAPPath"].ToString(), Usuario, Txt_Contrasenia.Text.ToString());
if (LDAPLogin.NativeGuid != LDAPLogin.Name)
ValidarGrupo();
}
catch (Exception exc)
{
Label_Info.Text = "Sus credenciales no son validas: " + Usuario.ToString() + " " + exc.Message;
}
If the user enters the rights credentials I call a method ValidarGrupo that implements a lookup in the AD for a group of the user
I would like to replace the username and password with UseDefaultCredentials in order to avoid that the user has to enter the username and password and the Login pages use the credentials of the user that is login on the machine.
I would like to replace the username
and password with
UseDefaultCredentials in order to
avoid that the user has to enter the
username and password and the Login
pages use the credentials of the user
that is login on the machine.
So you basically want to check whether the currently logged in user is valid?
I believe you can just simply create the DirectoryEntry without specifying any username/password - in that case, System.DirectoryServices will automatically use the current user credentials:
string ldapPath = ConfigurationSettings.AppSettings ["LDAPPath"];
DirectoryEntry LDAPLogin = new DirectoryEntry(ldapPath);
That should be enough, I believe!

Zend_Auth login using either username or email as identityColumn

I'm using Zend_Auth with a "Database Table Authentication". What I want to do is allow the user to login with either a username or email address as the "identityColumn". How would I allow both. I'm stuck.
Extend and implement your own Auth Adapter and use query like "WHERE username = ? or email = ?" to get Auth result :)
Authenticate twice (if needed) with 2 different Zend_Auth_Adapter_DbTable objects and add some logic to determine if the login is username or email by guessing if what type of login user provided so that you save one query for most of the cases.
I know this is not the cleanest Zend_Auth implementation, but it works. The only problem comes if someone registers with an different email address as a username, but of course you can prevent this in your registration form. Hope it helps.
// if the entered value validates as an email address then use the 'email' field
// if not, use the 'username' field
$validator = new Zend_Validate_EmailAddress();
if ($validator->isValid($form->getValue('password'))) {
$identityField = 'email';
} else {
$identityField = 'username';
}
$authAdapter = new Zend_Auth_Adapter_DbTable(
$dbAdapter,
'users',
$identityField,
'password',
'SHA1(?)'
);
$authAdapter->setIdentity($form->getValue('username'))
->setCredential($form->getValue('password'));