authorization on wicket component using wicket auth-role - wicket

I am using wicket 1.4.9 and implemented spring + wicket auth-role and using #AuthorizeInstantiation based on roles on pages. I have multiple custom roles.
I have followed this link to implement the basics:
https://cwiki.apache.org/WICKET/spring-security-and-wicket-auth-roles.html
After that I have implemented my own UserDetailsService to have my own roles/users from database.
Now, How can I impose controls on roles with components eg, Links,Buttons ? like
link A can be accessed only by SUPER_USER, DR_MANAGER. (roles comes from database).
I have done like this and it seems to work, but is that the good way to do this? OrbitWebSession is of type AuthenticatedWebSession.
#Override
public boolean isVisible() {
if(OrbitWebSession.get().getRoles().hasRole("SUPER_USER")){
return true;
}
return false;
}
thanks.

Overriding isVisible all the time is a major pain. Take a look at MetaDataRoleAuthorizationStrategy instead. You call authorize(Component component, Action action, String roles) with Action RENDER, and the roles you want to allow. This way the component, whatever it is, is automatically hidden for other roles provided that the authorization strategy is registered in your webapplication. Basically it does the same thing as Holms answer, except you don't have to subclass anything.

You are in the right track, the only change I would do is:
#Override
public boolean isVisible() {
return super.isVisible() && OrbitWebSession.get().getRoles().hasRole("SUPER_USER");
}
That way you don't accidentally override its default visible behavior for example if the parent component is not visible.

Using the #AuthorizeAction annotation you can control wether the component is rendered or not based on roles. It's quite easy to use, but you have to subclass the component that you want to authorize.
#AuthorizeAction(action = Action.RENDER, roles = { "SUPER_USER", "DR_MANAGER" })
class UserAdminPageLink extends BookmarkablePageLink<String> {
//Implementation…
}
add(new UserAdminPageLink("UserAdminPageLink", UserAdminPage.class));
Check out Wicket Examples - Authorization for some working code.

Related

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

RecyclerView on Multiple Activity

I have an app that depends heavily on recyclerview.. Each activity has different model and layout for them.. So do I need to write separate adapters for all of them.?? Or could I have a base adapter which can have on create view holder, onbind view holder which would reduce the amount of repetitive code..PS. I also need onclick listener so, I wanted to include that in the base adapter..
What is the best way?? And if I can write a base adapter please give me some code samples..
Thanks in Advance...
Each activity has different model and layout for them.. So do I need
to write separate adapters for all of them
Adapters are responsible for providing views that represent items in a data set, used by the RecyclerView. Now if those items in your ReyclerView are same across all the Activities then you can just have a single RecyclerView.Adapter
I also need onclick listener so, I wanted to include that in the base
adapter.. What is the best way??
You can check this SO post for detailed implementation, but I am summarizing it briefly.
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
})
);
And provide RecyclerItemClickListener class, that implements RecyclerView.OnItemTouchListener interface
And if I can write a base adapter please give me some code samples.
You need to clarify what exactly needs to be implemented in BaseAdapter for anyone to help you
yes it is possible
enter code here holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (modelArrayList.get(position).heading.equals("maps")){
Intent intent = new Intent(holder.button.getContext(),MainActivity2.class);
holder.button.getContext().startActivity(intent);
}
if (modelArrayList.get(position).heading.equals("calls")){
Intent intent = new Intent(holder.button.getContext(),MainActivity3.class);
holder.button.getContext().startActivity(intent);
}

easy way of showing errors in a wicket form

I am a wicket beginner and find it extremely hard to implement more advanced actions in it.
So I've got a form with input fields in it and a submit button. I've written my own validator with its own logic. now when the validator fails the page simply reloads and the wrong value is lost. what I want is:
inputs with wrong input(where the validator failed) should be graphically different, that is get its own style - can i do it in the validator itself? or do I have to implement a visitor? how do i register it for this very form? No error message is necessary.
the 'wrong input' should not be lost and should be visible to the user.
I'd be eternally thankful for a simple solution (with some code snippets please)
What you need is a Validator + Behavior.
The behavior is needed to modify the FormComponent's markup when it is invalid.
Fortunately they mix very well:
public class MyValidator extends Behavior implements IValidator<SomeType> {...}
Implement IValidator#validate(IValidatable) to validate (you already have this) and override Behavior#onComponentTag(Component, ComponentTag) to set a CSS class when invalid, e.g.:
#Override public void onComponentTag(Component c, ComponentTag tag) {
FormComponent fc = (FormComponent) c;
if (!fc.isValid()) {
tag.append("class", "error", " ");
}
}
Make sure you have a .css file loaded that defines .error with the desired styles. You can override Behavior#renderHead(Component, IHeaderResponse response) {response.render(CssHeaderItem.forReference(new CssResourceReference(SomeScope.class, "res/css/styles.css")))} for that.
I hope things a cleaner now.
Have fun!

Laravel user forms and admin forms: how to tackle?

Just a question to poll how you guys would tackle this in Laravel:
I have a user preferences page defined in UserController.php which creates the view at user/preferences.blade.php.
Administrators should of course be able to edit the user's preferences and have some extra administrative fields shown to be changed. Furthermore I'd like to collect all admin functionality concerning users in a separate controller called AdminUserController.php
I'm thinking of some possibilities to achieve this functionality:
Create an additional view (e.g. admin/user/preferences.blade.php) and almost replicate the GET and POST methods of UserController.php to accommodate the extra fields. However this seems to me like a lot of redundant code...
Convert the GET and POST methods of UserController.php to something like this:
public function postPreferences($user = NULL, $admin = FALSE) {
if (!isset($user)) $user = Auth::user();
// Process regular fields.
if ($admin) {
// Process admin fields.
}
}
Add the admin fields to user/preference.blade.php and conditionally show them if $admin is TRUE, and then call the UserController's methods from within AdminUserController, e.g.:
public function postPreferences($user) {
return (new UserController)->postPreferences($user, TRUE);
}
However, there are some drawbacks. First: controllers shouldn't call each other... Second: this only works for the POST method. Upon requesting the GET method from UserController an exception is being thrown...
I'm curious about how you would tackle this!
Thanks.
This is mostly a question of preference, but I really suggest you to completely separate all that is possible here. Administration is a process that is very sensitive and not in any way should it be possible, that a normal user will be able to see it under any circumstance.
I believe that we all are humans and we make mistakes more or less often, that's why we need to make sure that our mistakes in not assigning right value to the right variable or making a type of = instead of == not to ruin business logic.
I think you should make a separate view and a separate controller for user self management and administration and never tie them up. If you want to keep your code DRY as much as possible, you may extend your user controller and model from your admin controller and model, but not the other way around. That's just my 2 cents, it all depends on what type of application you are working on and what the stakes are.
<?php
class AdminController extends UserController
{
public function __construct(AdminModel $model)
{
// Use dependency injection
$this->model = $model;
}
// In the original UserController class:
public function postPreferences($user) {
$this->model->edit($user, Input::all());
// you may do it this way so your user only saves user data and
// you admin model saves all the data including administrative
}
// ...
}

MVC 2.0 - different view based on URL with shared controls

I have 2 master pages. One is intended to be shown in a normal standalone website. The other is to be used in external sites as an Iframe.
I want to be able to show the normal page at http://example.com/home/index and the iframed version at http://example.com/framed/home/index
I want to have controls that will postback to one controller so I don't have to duplicate logic, so they must be available in both the normal and iframed versions.
My problem is that when I try and use areas, I just can't get them to work right with the default url. Also, I have the added complication of structuremap. When I try and hit /area/controller/action, I get
The IControllerFactory
'MySite.Web.Code.IoC.StructureMapControllerFactory'
did not return a controller for the
name 'MyArea'.
Does anyone know how to make this kind of setup work? Really all I'm doing is trying to show one set of views if it has /Framed/controller/action and another set if it does not have /framed. I thought areas were the way to go, but maybe not.
All of our controllers implement the same base class, and we use the following override to do what you're describing:
protected override ViewResult View(string viewName, string masterName, object model)
{
if (masterName == null)
{
var options = PortalRequestManager.CurrentPortalRouteOptions;
masterName = options.MvcMasterPath;
}
return base.View(viewName, masterName, model);
}
All of our AreaRegistrations use the following method to register their areas:
public static void RegisterMvcAreaRoutes(AreaRegistrationContext context, string name, string url,
object defaults)
{
context.MapRoute(name + "Portal",
"P/Channel/" + url,
defaults);
context.MapRoute(name + "FramePortal",
"F/Channel/" + url,
defaults);
}
And then the PortalRequestManager that you saw in the first code block parses the URL to see if it uses "/P" or "/F" to determine which MvcMasterPath to use.
We use Ninject's controller factory, which has no problem with this setup, so I can't really speak to your problems with StructureMap.