OSMGeoAdmin shows textarea for PointField - django-admin

Here is my model:
from django.contrib.gis.db import models
class CustomUser(AbstractBaseUser, PermissionsMixin):
...
location = models.PointField(geography=True, dim=6, srid=4326, null=True)
I've registered it in the admin
from django.contrib.gis import admin
from project.accounts.models import CustomUser
admin.site.register(CustomUser, admin.OSMGeoAdmin)
But still got textarea for this field.
Where I am wrong?

You can try the documented way:
GeoDjango also supplements the Django admin by allowing users to
create and modify geometries on a JavaScript slippy map (powered by
OpenLayers).
in your admin.py:
from django.contrib.gis import admin
from project.accounts.models import CustomUser
admin.site.register(CustomUser, admin.GeoModelAdmin)
and don't forget your urls.py:
from django.contrib.gis import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
]

Related

Simple Spring Boot LDAP authentication example does not work with ActiveDirectory

I found a very simple example for LDAP authentication, which works just fine using an embedded LDAP server: https://github.com/asbnotebook/spring-boot/tree/master/spring-security-embedded-ldap-example . It is exactly what I need - one config class added and now all users are required to log in before accessing the application.
Since our AD (local server, not the Azure AD) requires userDN and password for access, I added this to the example code, also modified url, base dn etc.
When I attempt to log in, I always get the "Bad credentials" error message. I then stepped through the code and found that the Spring LDAP code successfully retrieves some user data from AD (I found the user email address in the "userDetails" object which is known only in the AD), however the "password" field is set to null. This null value is then compared to the password entered by the user which fails and a BadCredentialsException is thrown in function org.springframework.security.authentication.dao.additionalAuthenticationChecks().
So now I have two questions:
why is the "password" attribute set to null? My understanding is that it should contain the password hash. I checked the AD response with ldapsearch but I don't see anything looking like a password hash. However the userDN does work with other applications so it is probably not a problem with the userDN AD account. Please advise how to properly retrieve the password information.
I believe that the example does not handle password hashes. The LDIF file to preload the embedded LDAP server of the example application simply contains clear text passwords for the userPassword attribute. Also the passwordEncoder in the example code looks like a No Op Encoder. How should I change this to make it work with the AD?
Here is my code:
package com.asbnotebook.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.userdetails.LdapUserDetailsManager;
#Configuration
public class LdapSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public UserDetailsService userDetailsService() {
var cs = new DefaultSpringSecurityContextSource("ldaps://ad.company.local/dc=company,dc=local");
cs.setUserDn("cn=robot1,ou=robots");
cs.setPassword("secret");
cs.afterPropertiesSet();
var manager = new LdapUserDetailsManager(cs);
manager.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=company_user", "cn"));
manager.setGroupSearchBase("ou=company_groups");
return manager;
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
After considering Gabriel Luci's comment, I have now found a simple way to authenticate with our ActiveDirectory:
package com.asbnotebook.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
#Configuration
public class LdapSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
ActiveDirectoryLdapAuthenticationProvider adProvider =
new ActiveDirectoryLdapAuthenticationProvider(
"company.de","ldaps://ad.company.local","dc=company,dc=local");
adProvider.setConvertSubErrorCodesToExceptions(true);
adProvider.setUseAuthenticationRequestCredentials(true);
auth.authenticationProvider(adProvider);
auth.eraseCredentials(false);
}
}
Login is possible using either the email address or sAMAccountName.

Import dart:html in Service got exception No provider found for dynamic

I have a working UserService similar to HeroService from AngularDart tutorial with BrowserClient.
And now I need to use localStorage to save the API response.
After I import dart:html, I refresh my browser, suddenly I got error on console:
EXCEPTION: No provider found for dynamic: UserService -> dynamic.
When I remove the import, the service running well.
this is my UserService code.
import 'dart:convert';
import 'dart:html';
import 'package:http/http.dart';
import 'package:my_app/src/instance_logger.dart';
class UserService with InstanceLogger {
static final _headers = {'Content-Type': 'application/json'};
static const _authUrl = 'https://my.domain/api-token-auth/';
String get loggerPrefix => 'UserService'; // or set ''
final Client _http;
UserService(this._http);
dynamic _extractData(Response resp) => json.decode(resp.body)['data'];
Exception _handleError(dynamic e) {
log(e); // for demo purposes only
return Exception('Server error; cause: $e');
}
}
in Component meta-data:
providers: [ClassProvider(UserService)],
how to use dart:html within service? If I want to access localStorage.
thank you.
Both dart:html and package:http/http.dart unfortunately have a class named Client.
How you get around this collision is to hide an unwanted class from being imported with its package.
Change
import 'dart:html';
to
import 'dart:html' hide Client;
That will take care of the collision. You could alternatively give the import an alias such as:
import 'dart:html' as html;
Then you can use localStorage by using the prefix html.localStorage;
When I run into this problem I just hide the Client class from the dart:html import.

Injected dependency is null

Below are my two classes. Login and Activity. I want to inject Login into Activity. This occurs after Login has already been executed and parameters set. In file 2, login.UserName is always undefined and any other items I try to bind are undefined. Is there any thing that I am missing for proper binding?
//file 1
import {autoinject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import {bindable} from 'aurelia-framework';
import 'fetch';
#autoinject
export class Login{
#bindable UserName:String
constructor(private http: HttpClient){
...redacted...
}
login(){
this.UserName="test";
}
}
//file 2
import {autoinject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import 'fetch';
import {Login} from 'login/src/login';
#autoinject
export class Activity {
Login: Login;
constructor(private http: HttpClient, private login: Login) {
...redacted...
this.Login=login;
});
}
I think Activity class / custom-element is being injected with a different instance of the Login class / custom-element. Although the items are typically have container-controlled "singleton" lifetimes, UI components don't. I think you could get what you have to work by adding the #singleton to your Login ui component but you might be better off creating a separate class, possibly called "User" that you can inject into both the Login UI component and the Activity UI component.

How to allow User to login only once at a time?

I have used Spring Security Core plugin in my grails application, and I want to add the functionality:
When a user is already logged in, user will not be allowed to use same userName and password to login again using a different browser or a different machine altogether.
I think it should be somewhere in the spring security core but not sure.
It can be done using some configuration settings:
on the config.groovy, add this line:
grails.plugins.springsecurity.useHttpSessionEventPublisher = true
On the bootstrap.groovy:
import these two packages:
import org.codehaus.groovy.grails.plugins.springsecurity.SecurityFilterPosition
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
Then few dependency injections:
def authenticationManager
def concurrentSessionController
def securityContextPersistenceFilter
def authenticationProcessingFilter
def concurrentSessionControlStrategy
then register concurrency filter inside init(In Bootstrap):
authenticationProcessingFilter.sessionAuthenticationStrategy = concurrentSessionControlStrategy
SpringSecurityUtils.clientRegisterFilter('concurrencyFilter', SecurityFilterPosition.CONCURRENT_SESSION_FILTER)
and at the end in the resources.groovy:
import few packages:
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
import org.springframework.security.web.session.ConcurrentSessionFilter
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
then inside beans add:
sessionRegistry(SessionRegistryImpl)
concurrencyFilter(ConcurrentSessionFilter) {
sessionRegistry = sessionRegistry
logoutHandlers = [ref("rememberMeServices"), ref("securityContextLogoutHandler")]
expiredUrl='/login/concurrentSession'
}
concurrentSessionControlStrategy(ConcurrentSessionControlStrategy, sessionRegistry) {
alwaysCreateSession = true
exceptionIfMaximumExceeded = true
maximumSessions = 1
}
and done, now user can login only from one place.
I didn't tried it with the rememberMe option.
You can try using Persistent Logins and Remember-Me Cookie. The idea is to persist the remember-me token in database and check whether a cookie is present in the database or not in subsequent login attempts. If a cookie is present then disallow the login.
This has to work in conjunction with the key rememberMe.tokenValiditySeconds so that the token expires and is purged from the database.
You would get more insight and throw some light to this scenario if you look at
How to Create Persistent Token
Best Practices in Persistent Login
Remember-Me in Spring

Grails Spring security core pre-logout

I'm using Grails Spring Security Core plugin and I need to perform a few actions when logout happens such as delete some class instances related to the user. I tried the following code:
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import grails.plugins.springsecurity.Secured
class LogoutController {
def index = {
def currentUser = currentUser()
currentUser.searchedResults.each{searched->
def searchInstance = Search.get(searched.searchId)
searchInstance.delete()
}
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
private currentUser(){
return User.get(springSecurityService.principal.id)
}
}
However Grails is giving the error: No such property: User for class: LogoutController
My guess is that this is happening because when I installed Spring security core plugin, the LogoutController and LoginController were created in a different package called "default package". Is there any way to overcome this issue? Any help would be appreciated! Thanks
You simply need to import the User class. Something like:
import mypackage.User

Resources