Extending Restlet 2.3 ClientInfo - restlet

Is it possible to extend org.restlet.data.ClientInfo? I need a convenient way of adding a List<String> permissions to complement the existing List<Role> roles. In a perfect world I would be able to add List<Permission> permissions but the former is perfectly acceptable.
I need to be able to get this from the request: org.restlet.resource.Resource.getRequest().getClientInfo().getPermissions()

I don't think that it's possible to add something within the class ClientInfo since it's a class that is managed by the Restlet engine. You can't subclass it to add a field permissions (you don't have the hand on the client info instantiation).
That said, you can leverage the context attributes. I mean that you can fill within your Enroler implementation an attribute permissions for the request, as described below:
public class MyEnroler implements Enroler {
private Application application;
public MyEnroler(Application application) {
this.application = application;
}
public void enrole(ClientInfo clientInfo) {
// Roles
Role role = new Role(application, "roleId",
"Role name");
clientInfo.getRoles().add(role);
// Permissions
Request request = Request.getCurrent();
List<Permission> permissions = new ArrayList<Permission>();
request.getAttributes().put("permissions", permissions);
Permission permission = (...)
permissions.add(permission);
}
Hope it helps you,
Thierry

Related

Asp.net Boilerplate - Implement setting manager with database

I've been building an asp.net core website, using the asp.net boilerplate template. As of now, I've been storing all of the settings in the appsettings.json file. As the application gets bigger, I'm thinking I should start storing some settings via ABP's SettingProvider and ISettingStore.
My question is, does anyone have, or know of, a sample application that show's how to implement ISettingStore and storing the settings in the database?
The only post I could find so far is this, but the link hikalkan supplies is broken.
Thanks for any help,
Joe
ABP stores settings on memory with default values. When you insert a new setting value into database, then it reads from database and overrides the default value. So basically when database has no settings then it means all the settings are on default values. Setting values are stored in AbpSettings table.
To start using settings mechanism. Create your own SettingProvider inherited from SettingProvider. Initialize it in your module (eg:
ModuleZeroSampleProjectApplicationModule).
As SettingProvider is automatically registed to dependency injection; You can inject ISettingManager wherever you want.
public class MySettingProvider : SettingProvider
{
public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
{
return new[]
{
new SettingDefinition(
"SmtpServerAddress",
"127.0.0.1"
),
new SettingDefinition(
"PassiveUsersCanNotLogin",
"true",
scopes: SettingScopes.Application | SettingScopes.Tenant
),
new SettingDefinition(
"SiteColorPreference",
"red",
scopes: SettingScopes.User,
isVisibleToClients: true
)
};
}
}
In application services and controllers you don't need to inject ISettingManager
(because there's already property injected) and you can directly use SettingManager property. Forexample :
//Getting a boolean value (async call)
var value1 = await SettingManager.GetSettingValueAsync<bool>("PassiveUsersCanNotLogin");
And for the other classes (like Domain Services) can inject ISettingManager
public class UserEmailer : ITransientDependency
{
private readonly ISettingManager _settingManager;
public UserEmailer(ISettingManager settingManager)
{
_settingManager = settingManager;
}
[UnitOfWork]
public virtual async Task TestMethod()
{
var settingValue = _settingManager.GetSettingValueForUser("SmtpServerAddress", tenantAdmin.TenantId, tenantAdmin.Id);
}
}
Note: To modify a setting you can use these methods in SettingManager ChangeSettingForApplicationAsync, ChangeSettingForTenantAsync and ChangeSettingForUserAsync

list the api in swagger based on user roles

I have a requirement where I want to list the api methods in swagger based on user roles.
For example :-
User A with basic access can use limited api methods.
User B with Admin access can use all the listed api methods.
I don't know how to achieve this.
I am using Swashbuckle.AspNetCore Version="1.0.0"
Possible solution:
Define several dockets in your swagger config with different group names
#Bean
public Docket api1() {
...
return new Docket(DocumentationType.SWAGGER_2)
...
.groupName("api1")
...
.paths(PathSelectors.ant("/api/api1Url/**"))
.build().apiInfo(metaData());
}
#Bean
public Docket api2() {
...
return new Docket(DocumentationType.SWAGGER_2)
...
.groupName("api2")
...
.paths(PathSelectors.ant("/api/api2Url/**"))
.build().apiInfo(metaData());
}
Define your own DocumentationCache which overrides Swagger's one
#Primary
#Component
public class RolesAwareDocumentationCache extends DocumentationCache {
private final Map<String, Set<String>> allowedResourcesPerRole =
Map.of(SecurityConfig.API1_ROLE, Collections.singleton("api1"),
SecurityConfig.API2_ROLE, Collections.singleton("api2"),
SecurityConfig.SOME_ADMIN_ROLE, Set.of("api1", "api2"));
#Override
public Map<String, Documentation> all() {
var documentationMap = super.all();
return documentationMap.entrySet().stream()
.filter(e -> isAllowedForRole(e.getKey())) // check if has access to this group
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
private boolean isAllowedForRole(String groupName) {
var userAuthorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream()
.map(Object::toString)
.collect(Collectors.toUnmodifiableSet());
return userAuthorities.stream()
.map(allowedResourcesPerRole::get) // get allowed resources for all of the user roles
.filter(Objects::nonNull)
.flatMap(Collection::stream) // flatMap to collection
.anyMatch(s -> s.contains(groupName)); // check if result collection has specified group name
}
}
So this cache will return groups based on the current user's role from the security context. You can actually use any rules to restrict access to different groups.
Also do not forget to define proper permissions for HttpSecurity to restrict the invocation of an API for not allowed roles.
Try using an IDocumentFilter, you can limit what the user gets in the SwaggerDocument and the swagger-ui feeds from that.
Here are some examples https://github.com/heldersepu/SwashbuckleTest/blob/master/Swagger_Test/App_Start/SwaggerConfig.cs#L261

Implementing user session in Sencha and SpringBoot

I am trying to make a web app in Sencha Touch with Springboot as my back-end. My app is going to have users and each one of them is going to have their own separate activity. How do I make my app "know" what user is logged in so it can display their specific details? I am a newbie and don't know exactly how this needs to be done, especially on the server side (Springboot). If somebody could throw some light, that would be awesome! Thanks!
Assuming you are planning to use Spring Security, the current-user data can be obtained through its principal. There are a few ways to get the principal. One way is to have a principal parameter in the controller method, and Spring will inject it. Like this:
#RequestMapping(value = "/user", method = RequestMethod.GET)
#ResponseBody
public String currentUserName(Principal principal) {
return principal;
}
Another way would be to have a utility method like this:
public static User getUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
Object principal = auth.getPrincipal();
if (principal instanceof User) {
return (U) principal;
}
}
return null;
}
This can then be called from the controller method.

Overriding IAuthSession OnRegistered handler

I am using ServiceStack's SocialBootstrapApi and it contains a class CustomUserSession that I can use to override the OnRegistered method. I want to override it because I am attempting to obtain information about the registration so that I can publish an event that a new user has registered. This handler provides an instance of the RegistrationService that handled the registration but not anything about the registration request itself or the resulting UserAuth instance. For instance, I'd like to get the e-mail address used to register.
public override void OnRegistered(IServiceBase registrationService)
{
base.OnRegistered(registrationService);
// Ideally, I could do get the registered user's primary e-mail address from the UserAuth instance.
var primaryEmail = ((RegistrationService) registrationService)
.UserAuthRepo
.GetUserAuth(this, null) //<--- 'this' is a mostly empty session instance
.PrimaryEmail;
}
This of course doesn't work because the session instance I'm using for the GetUserAuth call doesn't contain any of the necessary authentication information to be useful for looking up the user's authentication information. So GetUserAuth returns null as you would expect. So how should I go about obtaining this information? Would it be incorrect design for the OnRegistered handler to be passed the UserAuth instance created by the RegistrationService?
public interface IAuthSession
{
...
void OnRegistered(IServiceBase registrationService, UserAuth userAuth); // <-- new signature
...
}
That would be convenient! :)
Or perhaps there's another way to go about this?
Thanks in advance.
So how should I go about obtaining this information?
You should be able to access all the data of the Registration request via the registrationService. You just have to do a little digging and casting...
public override void OnRegistered(IServiceBase registrationService)
{
base.OnRegistered(registrationService);
var requestContext = (HttpRequestContext)registrationService.RequestContext;
var dto = ((Registration)requestContext.Dto);
var primaryEmail = dto.Email;
}
Would it be incorrect design for the OnRegistered handler to be passed the UserAuth instance created by the RegistrationService?
I'll leave design decisions to the professionals. The above code should work. The casting seems a bit ugly but all the necessary data is there.
I do not like hack into SS, so I chose to select user auth info from UserAuth collection by dto.UserName

Role-based access control with Spring MVC

I would like to know the best practices for the role based access control with spring.
My requirements are,
I will have set of roles assigned to users say,
user1=admin, user2=expert
user1 will have the accesses write like
/admin/member-management
/admin/project-management
......
for user2....
/myproject1/*
so if user2 tries to access the url
/admin/member-management
will be redirect to authorization failure page.
The standard framework to use with Spring MVC is Spring Security. While it can be very complex, here's a minimal version of what you need: 4.2.2 A Minimal Configuration
In your case, the config would be something like this:
<http auto-config='true'>
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
</http>
Spring Security has the concept of roles but out of the box it does not have a concept of permissions. It does have a concept of ACLs but this ACLs are a lot more complicated than permissions, and they are tied to acting on specific objects, versus authorizing actions in general.
Take a look at Apache Shiro. It has roles and permissions that look very similar to what you gave as an example (using wildcards). It is also easy to use with Spring.
public class DashBoardController {
#Autowired
UserService userService;
private static final Logger logger = LoggerFactory.getLogger(DashBoardController.class);
#SuppressWarnings("unchecked")
#RequestMapping(value = PathProxy.DashBoardUrls.SHOW_DASHBOARD, method = RequestMethod.GET)
public String role(Locale locale, Model model) {
String userRole = null;
logger.info("dashboard Controller");
Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) SecurityContextHolder
.getContext().getAuthentication().getAuthorities();
for (SimpleGrantedAuthority simpleGrantedAuthority : authorities) {
userRole = simpleGrantedAuthority.toString();
}
switch (userRole) {
case "ROLE_ADMIN":
return "dashboard/admin";
case "ROLE_HR_MANAGER":
return "dashboard/hr_manager";
case "ROLE_MANAGER":
return "dashboard/manager";
case "ROLE_EMPLOYEE":
return "dashboard/employee";
case "ROLE_COMPANY_ADMIN":
return "dashboard/admin";
default:
break;
}
return userRole;
}
}