select list displayed with authrority not with id role in grails - grails-2.0

i have two class role and user
package tachemanagement.secu
class Role {
String authority
static hasMany = [users: User]
static mapping = {
cache true
}
static constraints = {
authority(nullable:true)
}
}
package tachemanagement.secu
class User {
transient springSecurityService
static belongsTo = [rol: Role]
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['springSecurityService']
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
}
*
i want to display a select list from role in user form
but the list displayed with name of id role (1,2,3) haw can be displayed with authority not just with id ?

Use toString() method in Role like the following
class Role{
String authority
static hasMany = [users: User]
static mapping = {
cache true
}
static constraints = {
authority(nullable:true)
}
String toString() {
"$authority"
}
}

Related

What would be the best/simplest solution to retrieve values from my database for comparison? - ASP.NET Core

I'm currently stuck on accessing all of the 'UserName' values from my database.
I am doing this so I can compare the user input for a username to check if it has been used before (I don't want two instances of the same username). This is on a .cshtml.cs page.
I am already able to access the database through my program, as create commands have been tested and do work.
My program is on ASP.NET 6.0 Core Web App.
I am a student with basic knowledge on ASP.NET Core, and on how to solve this issue, therefore as much simplified explanation would be very appreciated.
Here is my code:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using AQA_A_Level_CS_NEA__Suvat_Solver_.Models;
using AQA_A_Level_CS_NEA__Suvat_Solver_.Data;
namespace AQA_A_Level_CS_NEA__Suvat_Solver_.Pages.UserLogin
{
[BindProperties(SupportsGet = true)]
public class RegisterPageModel : PageModel
{
public new TempUserLoginModel TempUser { get; set; }
public bool HasPassword { get; set; } = true;
public bool HasUsername { get; set; } = true;
public bool UniUsername { get; set; } = true;
public bool RegisterApproved { get; set; } = false;
public bool AQAPhys { get; set; } = false;
public bool AQAMaths { get; set; } = false;
public bool SubjectChosen { get; set; } = true;
private readonly ApplicationDbContext _context;
public RegisterPageModel(ApplicationDbContext context)
{
_context = context;
}
public List<User> UserList = new List<User>();
public void OnGet()
{
}
public IActionResult OnPost()
{
User User = new User();
HasPassword = true;
HasUsername = true;
UniUsername = true;
SubjectChosen = true;
UserList = _context.User.ToList();
if (!AQAMaths && !AQAPhys)
{
SubjectChosen = false;
}
if (string.IsNullOrWhiteSpace(TempUser.Password) || TempUser.Password.Length < 4)
{
HasPassword = false;
}
if (string.IsNullOrWhiteSpace(TempUser.Username) || TempUser.Username.Length < 4)
{
HasUsername = false;
}
if (TempUser.Username == //database UserName value here )
{
//Here would be where the Username is compared
//UniUsername = false;
}
if (!HasPassword || !HasUsername || !UniUsername || !SubjectChosen)
{
return RedirectToPage("/UserLogin/RegisterPage", new { HasPassword, HasUsername, UniUsername, SubjectChosen });
}
else
{
RegisterApproved = true;
User.UserName = TempUser.Username;
User.UserPass = TempUser.Password;
User.UserCorrectAnsw = 0;
User.UserTotalAnsw = 0;
_context.User.Add(User);
_context.SaveChanges();
return RedirectToPage("/UserLogin/LoginPage", new { RegisterApproved });
}
}
}
}
Many Thanks.
Probably the strongest method is to enforce the user name column to be unique at the database level using a Unique Constraint. That way if you try to add a user with a duplicate user name, the database will simply return an error.
This article shows how to create a Unique Constraint with Entity Framework
You can be sure that the database will not allow a user with a duplicate user name with this method. However, trying to add a duplicate user will create an error which you will have to either handle or prevent from occurring in the first place (which is what you are doing now)
So for the code you are using now, since you already have the users pulled from the database here:
UserList = _context.User.ToList();
We can use LINQ to check if any of the users Usernames in UserList matches the TempUser like this:
if (UserList.Any(x => x.Username == TempUser.Username))
{
//Here would be where the Username is compared
UniUsername = false;
}
Since you didn't share your User model, this assumes your User class has a property named Username.
Happy Coding

JPA EntityManager doesn't commit changes in SQLite database

I have an SQLite database. I work with it using EclipseLink and JPA. In addition I have an entity class User:
import com.vaadin.server.VaadinService;
import java.io.Serializable;
import javax.persistence.*;
#Entity
public class User implements Serializable {
#Id #GeneratedValue
long id; // Unique identifier of the user in the DB
String username; // Unique name used for login
String password; // Password used for login
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
In a registration form I create a user and then call an EntityManager to persist() the changes:
public int createUser(String username, String password, String password_confirmation) {
int regStatus = 0;
if(checkValidUsername(username)) {
if(checkValidPassword(password, password_confirmation)) {
EntityManager em = factory.createEntityManager();
try {
em.getTransaction().begin();
User user = new User(username, password);
em.persist(user);
em.getTransaction().commit();
}
catch(Exception e) {
System.out.println(e.getMessage());
regStatus = 3;
}
finally {
em.close();
}
}
else regStatus = 2; // Password mismatch
}
else regStatus = 1; // User with selected username already present in DB
return regStatus;
}
It works without any problems. I get each and every newly registered user in my USER table. However when I try to change the password it doesn't work. Here are the methods that are related to this procedure:
// Inside the controller for my settings view - here the user can change various things related to his/her profile
public void setCurrentUser() {
currentUser = UserController.findUserByName((String)VaadinSession.getCurrent().getAttribute("username")); // findUserByName() is a static method
}
// Inside the User controller I have multiple methods for common user-related queries; here I use the username that I have retrieved from the VaadinSession's attribute "username" to execute a query and get the User entity (I make sure that a user's name is unique so getting a single result here is not a problem)
public static User findUserByName(String username) {
if(username == null) return null;
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
User user = null;
try{
Query q = em.createQuery("SELECT u FROM User u WHERE u.username = :username");
q.setParameter("username", username);
user = (User)q.getSingleResult();
}
catch(Exception e){
System.err.println(e.getMessage());
}
finally {
em.close();
}
return user;
}
// Inside the controller fpr my settings view (where I change the password)
public int changePassword(String currentPassword, String newPassword, String newPasswordConfirmation) {
if(newPassword.isEmpty()) return 1;
if(!newPassword.equals(newPasswordConfirmation)) return 2; // Incorrect confirmation
if(!currentPassword.equals(currentUser.getPassword())) return 3; // Given current password doesn't match the one stored in the database for this user
int resStatus = 0;
EntityManager em = factory.createEntityManager();
try {
em.getTransaction().begin();
currentUser.setPassword(newPassword);
em.getTransaction().commit(); // NO ERRORS at all...
}
catch(Exception e) {
System.out.println(e.getMessage());
resStatus = 4; // Exception
}
finally {
em.close();
}
return resStatus;
}
I have also tried using EntityManager.find(...), which should return the same row from the USER table (and it does) but the result is again the same - transaction begins, finishes, entity manager closes but the table USER for the supposedly changed user is the same.
Any ideas? I have used the same routine in another project but for setting other things. The database there was PostreSQL and I haven't encountered such issues. Here with the SQLite database I get no errors but the commit fails somehow.
I just develop with hibernate etc. but it will be the same, because both implements JPA.
If you start a transaction JPA will remember all entities you load in this transaction and if you change something you will see the changes in db (after commit).
But in your transaction JPA don't recognize your entity and so the changes will not persists. Try to load the entity in the transaction. Like...
em.getTransaction().begin();
em.find(User.class, currentUser.getId()); //Reload the User from db, so it is attached to the session
currentUser.setPassword(newPassword);
em.getTransaction().commit();
More Information about the methods:
https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#refresh(java.lang.Object)
https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#merge(T)
http://www.objectdb.com/java/jpa/persistence/managed

a request level singleton object in asp.net

I trying to write a kind of pseudo singleton implementation. I want it to work similar to how HttpContext does work, where I can get an instance to the context doing something as simple as:
var ctx = HttpContext.Current;
So my implementation goes something like this:
public class AppUser
{
public string Username { get; set; }
public string[] Roles { get; set; }
public AppUser()
{
var appuser = HttpContext.Session["AppUser"] as AppUser;
if(appuser == null)
throw new Exception("User session has expired");
Username = appuser.Username;
Roles = appuser.Roles;
}
}
public class WebAppContext
{
const string ContextKey = "WebAppContext";
WebAppContext() { } //empty constructor
public static WebAppContext Current
{
get
{
var ctx = HttpContext.Current.Items[ContextKey] as WebAppContext;
if(ctx == null)
{
try
{
ctx = new WebAppContext() { User = new AppUser() };
}
catch
{
//Redirect for login
}
HttpContext.Current.Items.Add(ContextKey, ctx);
}
return ctx;
}
}
public AppUser User { get; set; }
}
And I try to consume this object as follows:
var appuser = WebAppContext.Current.User;
Now does the above line guarantee I get the user associated with the correct request context; not some other user which is associated with another concurrent http request being processed?
Apart from the fact that I can't understand why would you need to barely copy the user information from the Session container to the Items container, the answer to your question should be - yes, if the Session data is correct then the same data will be available from your static property.
I wrote a blog entry on that once
http://netpl.blogspot.com/2010/12/container-based-pseudosingletons-in.html

How to use new MVC5 Authentication with existing database

I've looked through the current literature but I'm struggling to workout exactly how to make the new IdentityStore system work with your own database.
My database's User table is called tblMember an example class below.
public partial class tblMember
{
public int id { get; set; }
public string membership_id { get; set; }
public string password { get; set; }
....other fields
}
currently users login with the membership_id which is unique and then I use the id throughout the system which is the primary key. I cannot use a username scenario for login as its not unique enough on this system.
With the examples I've seen it looks like the system is designed to me quite malleable, but i cannot currently workout how to get the local login to use my tblmember table to authenticate using membership_id and then I will have access the that users tblMember record from any of the controllers via the User property.
http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-forms-authentication-in-mvc-5.aspx
Assuming you are using EF, you should be able to do something like this:
public partial class tblMember : IUserSecret
{
public int id { get; set; }
public string membership_id { get; set; }
public string password { get; set; }
....other fields
/// <summary>
/// Username
/// </summary>
string UserName { get { return membership_id; set { membership_id = value; }
/// <summary>
/// Opaque string to validate the user, i.e. password
/// </summary>
string Secret { get { return password; } set { password = value; } }
}
Basically the local password store is called the IUserSecretStore in the new system. You should be able to plug in your entity type into the AccountController constructor like so assuming you implemented everything correctly:
public AccountController()
{
var db = new IdentityDbContext<User, UserClaim, tblMember, UserLogin, Role, UserRole>();
StoreManager = new IdentityStoreManager(new IdentityStoreContext(db));
}
Note the User property will contain the user's claims, and the NameIdentifier claim will map to the IUser.Id property in the Identity system. That is not directly tied to the IUserSecret which is just a username/secret store. The system models a local password as a local login with providerKey = username, and loginProvider = "Local"
Edit: Adding an example of a Custom User as well
public class CustomUser : User {
public string CustomProperty { get; set; }
}
public class CustomUserContext : IdentityStoreContext {
public CustomUserContext(DbContext db) : base(db) {
Users = new UserStore<CustomUser>(db);
}
}
[TestMethod]
public async Task IdentityStoreManagerWithCustomUserTest() {
var db = new IdentityDbContext<CustomUser, UserClaim, UserSecret, UserLogin, Role, UserRole>();
var manager = new IdentityStoreManager(new CustomUserContext(db));
var user = new CustomUser() { UserName = "Custom", CustomProperty = "Foo" };
string pwd = "password";
UnitTestHelper.IsSuccess(await manager.CreateLocalUserAsync(user, pwd));
Assert.IsTrue(await manager.ValidateLocalLoginAsync(user.UserName, pwd));
CustomUser fetch = await manager.Context.Users.FindAsync(user.Id) as CustomUser;
Assert.IsNotNull(fetch);
Assert.AreEqual("Custom", fetch.UserName);
Assert.AreEqual("Foo", fetch.CustomProperty);
}
EDIT #2: There's also a bug in the implementation of IdentityAuthenticationmanager.GetUserClaims that is casting to User instead of IUser, so custom users that are not extending from User will not work.
Here's the code that you can use to override:
internal const string IdentityProviderClaimType = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider";
internal const string DefaultIdentityProviderClaimValue = "ASP.NET Identity";
/// <summary>
/// Return the claims for a user, which will contain the UserIdClaimType, UserNameClaimType, a claim representing each Role
/// and any claims specified in the UserClaims
/// </summary>
public override async Task<IList<Claim>> GetUserIdentityClaims(string userId, IEnumerable<Claim> claims) {
List<Claim> newClaims = new List<Claim>();
User user = await StoreManager.Context.Users.Find(userId) as IUser;
if (user != null) {
bool foundIdentityProviderClaim = false;
if (claims != null) {
// Strip out any existing name/nameid claims that may have already been set by external identities
foreach (var c in claims) {
if (!foundIdentityProviderClaim && c.Type == IdentityProviderClaimType) {
foundIdentityProviderClaim = true;
}
if (c.Type != ClaimTypes.Name &&
c.Type != ClaimTypes.NameIdentifier) {
newClaims.Add(c);
}
}
}
newClaims.Add(new Claim(UserIdClaimType, userId, ClaimValueTypes.String, ClaimsIssuer));
newClaims.Add(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String, ClaimsIssuer));
if (!foundIdentityProviderClaim) {
newClaims.Add(new Claim(IdentityProviderClaimType, DefaultIdentityProviderClaimValue, ClaimValueTypes.String, ClaimsIssuer));
}
var roles = await StoreManager.Context.Roles.GetRolesForUser(userId);
foreach (string role in roles) {
newClaims.Add(new Claim(RoleClaimType, role, ClaimValueTypes.String, ClaimsIssuer));
}
IEnumerable<IUserClaim> userClaims = await StoreManager.Context.UserClaims.GetUserClaims(userId);
foreach (IUserClaim uc in userClaims) {
newClaims.Add(new Claim(uc.ClaimType, uc.ClaimValue, ClaimValueTypes.String, ClaimsIssuer));
}
}
return newClaims;
}

How to localize WebParts attributes within the PropertyEditorPart?

Is there any way to localize the text displayed within the PropertyEditorPart?
[Personalizable(true),
WebBrowsable(true),
WebDisplayName("To Date: "),
WebDescription("Please enter To Date value.")]
public string ToDate
{
get { return toDate; }
set { toDate = value; }
}
To achieve this, these attributes (Category, WebDisplayName and WebDescription) should be extended so they take advantage of the localization features.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class LocalizedWebDisplayNameAttribute
: WebDisplayNameAttribute {
bool m_isLocalized ;
public LocalizedWebDisplayNameAttribute(string displayName)
: base(displayName) {
}
public override string DisplayName {
get {
if (!m_isLocalized) {
this.DisplayNameValue =
Resources.ResourceManager.GetString(
base.DisplayName, Resources.Culture);
m_isLocalized = true;
}
return base.DisplayName;
}
}
}
More details, Web Part Properties - part 5 - localization

Resources