I am working on a application which has several companies as our clients and multiple users under each company which access our application.
So I have structured the table of users to save users of all companies in same table and have the company_id as a column-
class User {
String username
String password
static belongsTo = [company:Company]
static constraints = {
username blank: false
password blank: false
}
}
In this app I have customised the spring security to authenticate the user based on 3 fields- username, password and comapany. So if there are two users ABC in company Org1 and Org2 they will be identified properly.
Now if I apply the constraint of unique: true on username the constraint is applied on whole table and it does not allow me to save two users ABC, no matter if they are on two different companies.
(PS- I understand constraint is based on table, kindly read further).
Now the main problem is that I want to make the username unique based on the company not based on User table. How to do that? Is there a predefined constraint that can be used to check if the username is present in the company? Or will have to check it each time while registering, if the username already exits in a company?
You could try to use a multi-column constraint (see http://www.grails.org/doc/latest/ref/Constraints/unique.html)
Your username constraint would look something like this:
username blank: false, unique: 'company'
Related
my question is: (How?) can I store my "authority" for my user in the user class in Grails with the Spring Security Plugin?
I've given the following SQL structure:
User table:
...
varchar(255): username
...
int(2) rank: (refers to Rank table)
Rank table:
int(11): id
varchar(25): rank_name
Can I configure my domain classes, to work with that structure instead of the typical "User, Authority, UserAuthority many to many" schema?
The rank (id) is hierarchial, that means a user with the rank 4 got all "authorities" from a user with rank 3 etc.
EDIT:
I simply replaced in the User Domain, the getAuthorities method with the following:
Set<Permission> getAuthorities() {
Authority.findAllById(this.rank)
// instead of: UserAuthority.findAllByUser(this)*.permission
}
Look at GormUserDetailsService to see how authorites are loaded.
There's an authoritiesPropertyName configuration for springsecurity core, which specifies the property name of user domain which should return the authorities, the default value is 'authorities' -- you can modify this to return the authorities based on your domain model.
If this does not satisfy your requirement then You can create a custom user details service too.
And override the original user details service by defining a bean with name userDetailsService in your conf/spring/resources.groovy
I have a Users table, along with Roles table with many to many relation
Users
Id, Name, Password, ICollection<Role> ....
Roles
Id, Name
and UsersRoles
UserId, RoleId
Now if I retrieve a user object from the database and modify the Password field of example, an exception will occur if i don't load the roles even though I'm not touching the roles of the user.
So the question is: how can I update the Users table without retrieving all the roles every time?
I am currently using Asp MVC / Identity 2.0 to build a membership site.
I have made some changes that now allow a user todo the following :
Create separate username / email values on account creation
Login using either username or email through a single text field
What I am concerned about is should user Alice register an account as follows :
Username - Alice
Email - alice#example.com
User Bob could create an account as follows :
Username - alice#example.com
Email - evilbob#l33th4x0rs.com
I'd like to ensure, that should a user create an account, their username is unique in both the UserName and EmailAddress columns.
I have currently achieved within my RegisterViewModel as follows
[RegularExpression(#"^([a-zA-Z0-9 \.\&\'\-]+)$", ErrorMessage = "{0} must be alpha numeric")]
[Display(Name = "Username")]
public string UserName { get; set; }
As such it is not possible to enter an email into the username field - is this the best way to do this though?
I'm concerned that later down the line, I may want to allow some special characters in the username field.
Forgive me if this is a n00b question, I'm still very much new to this.
You cannot ensure uniqueness of your records using the Data annotations you have in your view model properties. Those are for helping validations & display purposes primarily.
What you should be doing is checking the userName value againist both UserName and Email field of your User table and allow/deny user to continue his action.
To check the userName against both email and userName fields , you might try something like this.
var userNameToCheck="alice#ss.com";
var exists=db.Users.Any(x=>x.UserName==userNameToCheck||x.Email==userNameToCheck);
if(!exists)
{
// New record. Let's continue saving it.
}
But a better solution is to use email as your username for the app(Only one column in db table) and keep a unique constraint on that column(Email) to prevent accidental duplicate entry even if your code failed to stop the duplicate entry insertion.
You should always have validation in your code and db (constraints) to be on the safer side.
I am developing a ASP NET MVC 5 website wherein I need to provide a WebApi for a WPF client. The client needs to send user name and password for the user, and the WebApi needs to check whether the user name and password are correct and whether the user name belongs to the admin role (defined by my website).
I am using Visual Studio 2013, so for adding roles, I directly add entries into AspNetRoles and AspNetUserRoles tables using Server Explorer. (say for example, I added admin role, and mapped user1 to admin role)
I find that to check the user name and password is correct, I can use the same code as used by the login functionality in the default account controller. I am finding trouble finding an API to check user name against a role name. I am not adding roles programmatically; I just want to check whether user1 was mapped to the admin role in the AspNetUserRoles table.
Can anyone suggest how to do that ?
It is quite easy actually. You can perform checking roles at the point where the user has authenticated successfully.
Let's say that there is a user repository with the following function:
internal interface IUserReporsitory
{
bool IsUserInRole(int userId, string rolename);
}
The function then checks for the a record in the UsersRole table for the user id and the rolename.
public class UserReporsitory : IUserReporsitory
{
public bool IsUserInRole(object userId, string roleName)
{
//Query the UsersInRole tables Join the Role Table for the user with Id = userId and RoleName=roleName
}
}
The actual implementation is a matter of an SQL query to the database.
I am using a string "username" as the primary-key of a table,
But when saving and getting the column with the username id I want the case to be ignored so that new users can't try to impersonate another user.
e.g. When registering a new user
username = Daxon
username = DaXoN //this should not be allowed
When getting the unique username it can be typed in any case and still be obtained.
Youtube do this with their usernames.
e.g.
youtube.com/user/Daxon
youtube.com/user/DaXoN //Should go to the same profile of 'Daxon' anyway
Domain Class
This uses username as the primary key
class User {
String username
String password
static constraints = {
}
static mapping = {
id generator: 'assigned', name: "username", type: 'string'
}
}
I then scaffold the controllers and views,
so can anyone help me on saving and getting unique usernames with case ignored?
One way you can prevent the second user from registering a name that differs only in case is to create a case insensitive unique index on username at the database layer. If you try to save a name that case-insensitively matches an existing one, you'll get a database exception. This is the default with mysql, but for other databases, something like the following should do it:
create unique index username_csunique_idx on user(lower(username));
I'm not aware of any way to specify that kind of index in the domain class DSL.
To find the objects, query by username case insensitively. For example, User.findByUsernameIlike(userName), or User.find("from User as u where lower(u.username) = ?", [userName.toLowerCase()]) if you prefer HQL.
You can modify your save and get methods of the generated controler to do string comparrisons. Before inserting a username you could do an HQL query that does a case insensitive comparrison on the user name you want to insert to make sure that no user name already exists. See the "HQL And Case Sensitivity" section of the following link. http://dev.wavemaker.com/wiki/bin/view/Dev/HqlTutorial#HCaseInsensitiveQuery