I'm using spring ldap with OpenDJ and was not able to set the attribute isMemberOf or memberOf for the person. Also, I'm having problem to get createdTimestamp and modifiedTimestamp attributes for the person. Please help
The createTimeStamp and modifyTimeStamp LDAP attributes are by specification Operational and read-only: they are set automatically by the server when the entry is created (LDAP ADD operation) or modified.
The isMemberOf is also an operational and read-only attribute in OpenDJ. It is a backlink between a Group and a user. It's computed on the fly, based on Static or Dynamic group. Add the user DN to a group, and you will be able to read the isMemberOf attribute in the user entry.
In my implementation, which currently uses Spring LDAP repositories (spring-boot-starter-data-ldap version 3.0.0-M3) and Oracle Unified Directory (OUD), I was able to fetch the operational attribute isMemberOf by simply including the #Attribute annotation on the appropriate user property.
For example:
#Entry(...)
public class AppUser implements UserDetails {
// ... other fields ...
#Attribute(name = "isMemberOf")
private List<String> groups;
// ... getters/setters ...
}
#Repository
public interface AppUserRepository extends LdapRepository<AppUser> {
}
By fetching a user with the repository's findOne() method, and without any additional configuration, it correctly populated the groups property. However, as mentioned in the other answer, it's read-only; to set the isMemberOf, you would need to add the user DN to any relevant groups.
Related
I cannot understand why Authority is so complex in JHipster? What's the reason for creating another entity with only one field name? Furthermore it has a csv file that uploads a template to the database with Liquibase.
There was an idea for me to create an enum (see this answer):
#Entity
#Table
public enum Authority {
USER, ADMIN;
#Id
private String title = "ROLE_" + name();
}
Then I decided that this is not necessary too. It can be an enum without annotations and just a Set (or even an EnumSet):
private Set<Authority> authorities = new HashSet<>();
Did I miss something? Maybe it's useful for JPA?
I wanted to create an issue on GitHub but I think it's a better place.
GrantedAuthority is defined by Spring Security and default implementation SimpleGrantedAuthority has only a role name but it can be extended to have more attributes so I guess that JHipster's entity enables this possibility.
In my project, Admin adds Instructors, then each Instructor adds his students. When they are added, they'll receive an email asks them to complete registration .
I have the following classes in my project :
1-Student class
Student: int id, int Registry number, int grade, string password, string email, string name
2-Instructor class:
Instructor: int id, string name , string email , string password
3-My database context:
public class InstructorContext:DbContext
{
public InstructorContext() : base("InstructorContext")
{
}
public DbSet<Instructor> Instructors { get; set; }
public DbSet<Student> Students { get; set; }}
When a user loges in , I must determine whether he is an Admin or Instructor or Student. Do I have to use role-based authentication? I already have 2 separate classes for different roles. Is it possible for both of them to inherit from IdentityUser?
No, you cannot have multiple user tables with Identity, at least not technically. All the other core components of Identity (roles, claims, logins, etc.) are setup with foreign keys to one user table.
For your scenario here, you should use inheritance. For example:
public class ApplicationUser : IdentityUser
public class Instructor : ApplicationUser
public class Student : ApplicationUser
By default, Entity Framework will create the one table for ApplicationUser and add a Discriminator column to it. This column will have one of three possible values: "ApplicationUser", "Instructor", and "Student". When EF reads from this table, it will use this column to instantiate the right class. This is what's known as single-table inheritance (STI) or alternatively as table-per-hierarchy (TPH). The main downside to this approach is that all of the properties for all of the classes must be represented on the same table. If you're creating a new Student for example, the columns for an Instructor would still be on the record, only with nulls or defaults for those values. This also means that you can't enforce a property on something like Instructor be required at the database level, as that would prevent saving ApplicationUser and Student instances which are unable to provide those values. In other words, all your properties on your derived classes must be nullable. However, you can always still enforce something like a property being required for the purpose of a form using view models.
If you really want to have separate tables, you can somewhat achieve that goal by changing the inheritance strategy to what's called table-per-type (TPT). What this will do is keep the table for ApplicationUser, but add two additional tables, one each for Instructor and Student. However, all the core properties, foreign keys, etc. will be on the table for ApplicationUser, since that is where those are defined. The tables for Instructor and Student would house only properties that are defined on those classes (if any) and a foreign key to the table for ApplicationUser. When querying, EF will then do joins to bring in the data from all of these tables and instantiate the appropriate classes with the appropriate data. Some purists like this approach better as keeps the data normalized in the database. However, it's necessarily heavier on the query side because of the joins.
One last word of caution, as this trips people up constantly dealing with inheritance with Identity. The UserManager class is a generic class (UserManager<TUser>). The default instance in AccountController, for example, is an instance of UserManager<ApplicationUser>. As a result, if you use that instance, all users returned from queries will be ApplicationUser instances, regardless of the value of the Discriminator column. To get Instructor instances, you would need to instantiate UserManager<Instructor> and use that for your Instructor-related queries.
This is especially true with creating users for the first time. Consider the following:
var user = new Instructor();
UserManager.Create(user);
You might expect that the user would be saved with a discriminator value of "Instructor", but it will actually be saved with "ApplicationUser". This is because, again, UserManager is an instance of UserManager<ApplicationUser> and your Instructor is being upcasted. Again, as long as you remember to use the appropriate type of UserManager<TUser> you'll be fine.
I want to store Contacts on to Azure table(name and gender as a property). so I basically two classes . the one which derives from the TableSerivceContext and the other from TableServiceEntity. now I cant connect the pieces. What I will really do at the cotroller(I use MVC3)
tnx for any hint?
im assuming that you are receiving the properties (name and gender) via post from a view.
so your controller might be like this
public ActionResult DoSomething(User model)
{
}
so what you need to do is.. that. make a new ofject of the class thats derived from the TableServiceEntity. and assign the Properties.
like this
var tableUser = new TableUser(){Name = model.Name, Gender=model.Gender}
then from the class derived from TableServiceContext make an object. and use AddObject() method to add the user to the table
http://msdn.microsoft.com/en-us/library/system.data.services.client.dataservicecontext.addobject.aspx
This is what I have done recently to create a very simple MVC3 + Windows Azure Table sample application:
Created a Model Class DataEntity inherit from TableServiceEntity which include all the table properties needed to store along with PartitionKey and RowKey
Created another Model class DataContext inherit from TableServiceConext which includes IQueryable sets up the Table
Created a Controller class which creates HTTPGet and HTTPPost method type ViewResult returning View. The controller also have code to create the Table first using Model DataContext type and then added code to call AddObject as DataEntity type as below:
DataContext context = new DataContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
context.AddObject("DataEntryTable", dataEntity);
context.SaveChanges();
Finally you can create views from the controllers.
You would need to inherit ‘Contact’ from TableServiceEntity and a context class from TableServiceContext to provide all the methods to manage your ‘Contact’ entities. You can then invoke methods on the ‘Context’ class from anywhere (including the controller).
I have written an alternate Azure table storage client, Lucifure Stash, which does away with having to inherit from any base calls and supports additional abstractions over azure table storage. Lucifure Stash supports large data columns > 64K, arrays & lists, enumerations, composite keys, out of the box serialization, user defined morphing, public and private properties and fields and more.
It is available free for personal use at http://www.lucifure.com or via NuGet.com.
Download the Windows Azure Platform Training Kit and do the lab on Windows Azure Storage. In 15 minutes you will have a working prototype.
I'm wondering what is good approach to secure handler method in Spring MVC controller. Now i use #Secured annotation, that ensure that some method may be accessed by logged user only. But how to ensure that one logged user doesn't do something bad for other users ? For example i have method that delete item with given id. To ensure that someone can't remove other than his items i check item owner. Is better way to do something like that ?
#Secured("ROLE_USER")
#RequestMapping("/deleteitem.html")
public String delete(#RequestParam(value="id") Long id) {
Item b = itemDAO.get(id);
if(b.getOwner().getId().equals(((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser().getId())) {
itemDAO.delete(id);
}
return "redirect:/user/items.html";
}
Perhaps you can look at #Preauthorize annotation. You can do something like
#PreAuthorize("#item.id == authentication.id")
public void doSomething(Item item);
You would need to rewrite your current code suitably.
Look into Spring Security ACL (Access control list) you can create a list of permissions that users have for this object. Permissions include read, write, delete...
You need to implement role base system, base on privileges user can perform delete operation.
If specific user having delete access then he/she do the delete stub.
I'm trying to figure out how to accomplish the following:
User can have many Websites
What I need to do before adding a new website to a user, is to take the website URL and pass it to a method which will check whether the Website already exist in the database (another User has the same website associated), or whether to create a new record. <= The reason for this is whether to create a new thumbnail or use an existing.
The problem is that the repository should be per aggregate root, which means I Cant do what I've Explained above? - I could first get ALL users in the database and then foreach look with if statement that checks where the user has a website record with same URL, but that would result in an endless and slow process.
Whatever repository approach you're using, you should be able to specify criteria in some fashion. Therefore, search for a user associated with the website in question - if the search returns no users, the website is not in use.
For example, you might add a method with the following signature (or you'd pass a query object as described in this article):
User GetUser(string hasUrl);
That method should generate SQL more or less like this:
select u.userId
from User u
join Website w
on w.UserId = u.UserId
where w.Url = #url
This should be nearly as efficient as querying the Website table directly; there's no need to load all the users and website records into memory. Let your relational database do the heavy lifting and let your repository implementation (or object-relational mapper) handle the translation.
I think there is a fundamental problem with your model. Websites are part of a User aggregate group if I understand correctly. Which means a website instance does not have global scope, it is meaningful only in the context of belonging to a user.
But now when a user wants to add a new website, you first want to check to see if the "website exists in the database" before you create a new one. Which means websites in fact do have a global scope. Otherwise anytime a user requested a new website, you would create a new website for that specific user with that website being meaningful in the scope of that user. Here you have websites which are shared and therefore meaningful in the scope of many users and therefore not part of the user aggregate.
Fix your model and you will fix your query difficulties.
One strategy is to implement a service that can verify the constraint.
public interface IWebsiteUniquenessValidator
{
bool IsWebsiteUnique(string websiteUrl);
}
You will then have to implement it, how you do that will depend on factors I don't know, but I suggest not worrying about going through the domain. Make it simple, it's just a query (* - I'll add to this at the bottom).
public class WebsiteUniquenessValidator : IWebsiteUniquenessValidator
{
//.....
}
Then, "inject" it into the method where it is needed. I say "inject" because we will provide it to the domain object from outside the domain, but .. we will do so with a method parameter rather than a constructor parameter (in order to avoid requiring our entities to be instantiated by our IoC container).
public class User
{
public void AddWebsite(string websiteUrl, IWebsiteUniquenessValidator uniquenessValidator)
{
if (!uniquenessValidator.IsWebsiteUnique(websiteUrl) {
throw new ValidationException(...);
}
//....
}
}
Whatever the consumer of your User and its Repository is - if that's a Service class or a CommandHandler - can provide that uniqueness validator dependency. This consumer should already by wired up through IoC, since it will be consuming the UserRepository:
public class UserService
{
private readonly IUserRepository _repo;
private readonly IWebsiteUniquenessValidator _validator;
public UserService(IUserRepository repo, IWebsiteUniquenessValidator validator)
{
_repo = repo;
_validator = validator;
}
public Result AddWebsiteToUser(Guid userId, string websiteUrl)
{
try {
var user = _repo.Get(userId);
user.AddWebsite(websiteUrl, _validator);
}
catch (AggregateNotFoundException ex) {
//....
}
catch (ValidationException ex) {
//....
}
}
}
*I mentioned making the validation simple and avoiding the Domain.
We build Domains to encapsulate the often complex behavior that is involved with modifying data.
What experience shows, is that the requirements around changing data are very different from those around querying data.
This seems like a pain point you are experiencing because you are trying to force a read to go through a write system.
It is possible to separate the reading of data from the Domain, from the write side, in order to alleviate these pain points.
CQRS is the name given to this technique. I'll just say that a whole bunch of lightbulbs went click once I viewed DDD in the context of CQRS. I highly recommend trying to understand the concepts of CQRS.