I have a class called App with some fields.
I want to initalize the final fields only if passed parameters to constructor are not null.
e.g in below code I want to set config param only if it is not null.
I tried below code but it is not working
#immutable
class App {
final AuthState auth;
final RConfig config;
App({AuthState auth, this.config}):
auth = auth ?? new AuthState(), config = config != null ? config : this.config ;
Although I am quite new to dart, I know that I can't initalize final fields twice but there are app states due to which AppState get created again and RConfig may be null at that time.
My question is as simple is this how to check multiple final fields validity e.g null or empty before assigning them.
You cannot initialize a field twice. You initialize config both with an initializing formal (this.config) and an initializer list entry config = ....
I'm not sure what you are trying to do with config, but start by declaring it as a normal parameter, then figure out what you want to do:
AppState({AuthState auth, RConfig config})
: auth = auth ?? new AuthState(), config = config; // or something
Related
I want to store data in an object and I want to use this in the whole app. I created an Object and register as Singleton in Program.cs
Object:
private Dictionary<string, string> _currentValues;
public Dictionary<string, string> currentValues
{
get => _currentValues;
set
{
_currentValues = value;
StateHasChanged();
}
}
Singleton Registration:
services.AddSingleton<LocalizeData>();
In program.cs after registration I added initial data.
var _localizeData = host.Services.GetRequiredService<LocalizeData>();
_localizeData.currentValues = locaData;
Now I want to use these data in the whole app. I injected it main Page.
#LocalizeData localizeData
If I use now localizeData.currentValues the object is null.
What is missing. How can I initialize an object in Starttup and how can I use the data in whole app?
You're almost there. :D
To use services in your component, you need to use the inject keyword:
#inject LocalizeData localizeData
The Problem was I used
await builder.Build().RunAsync();
instead of
await host.RunAsync();
This was the reason why I created a second instance and I could not access my initialize data.
See documentation:
https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/dependency-injection?view=aspnetcore-5.0&pivots=webassembly
The former HtmlHelper.AntiForgeryToken method which allows one to override the string path is deprecated.
[ObsoleteAttribute("This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the <httpCookies> configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property.",
true)]
public MvcHtmlString AntiForgeryToken(
string salt,
string domain,
string path
)
Tells you to use <httpCookies>. BUT httpCookies Element does not have a setting for PATH.
Is this an oversight in the deprecation of this method? What is the best way to overwrite this cookie path? (manually?) Running website in a virtual application is not implicitly adding the application path to the __RequestVeririfcation cookie.
Looking at the deprecation message:
"This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property."
It tells us we can validate additional parameters whenever the forgery token is read back. So even if we can't set the path in the cookie, we can set the path as a property inside the token. To validate it later on, for example:
public class AdditionalDataProvider : IAntiForgeryAdditionalDataProvider
{
public string GetAdditionalData(HttpContextBase context)
{
return AdditionalData(context);
}
public bool ValidateAdditionalData(HttpContextBase context, string additionalData)
{
var currentData = AdditionalData(context);
return currentData == additionalData;
}
private static string AdditionalData(HttpContextBase context)
{
var path = context.Request.ApplicationPath;
return path;
}
}
When asp.net generates the token it will store the current path (or any other unique value you want to validate) for that app and
if you have another app running on a different path, when the token gets sent to that app (due to the lack of cookie path) it will validate the previous app properties against that app's properties. If it is a different set of properties it will fail and deny the request.
Additionally, looking at the code for the AntiforgeryConfig.cs, if the app is running in a virtual directory, it will add that virtual directory in the cookie's name by default:
private static string GetAntiForgeryCookieName()
{
return GetAntiForgeryCookieName(HttpRuntime.AppDomainAppVirtualPath);
}
// If the app path is provided, we're generating a cookie name rather than a field name, and the cookie names should
// be unique so that a development server cookie and an IIS cookie - both running on localhost - don't stomp on
// each other.
internal static string GetAntiForgeryCookieName(string appPath)
{
if (String.IsNullOrEmpty(appPath) || appPath == "/")
{
return AntiForgeryTokenFieldName;
}
else
{
return AntiForgeryTokenFieldName + "_" + HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(appPath));
}
}
So it will be like this:
_RequestVerificationToken vs
_RequestVerificationToken_L2RIdjAz0
Meaning App2 although can receive tokens from App1, it won't be able to read them since it will be looking always for App2 verification token only.
HTH
For ASP.NET Core - See: AntiforgeryOptions Class
Cookie - Determines the settings used to create the antiforgery
cookies.
Ex (adapted from Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core):
services.AddAntiforgery(options =>
{
options.Cookie.Path = "Path";
});
The best aproach to overwrite AntiForgeryToken's cookie configuration (Path, HttpOnly,...) is with encapsulation (Microsoft team post).
It is possible to configure the cookie path instead of setting it on the properties.
public static class AntiForgeryTokenExtensions
{
///<summary>
///Generates a hidden form field (anti-forgery token) that is
///validated when the form is submitted. Furthermore, this extension
///applies custom settings on the generated cookie.
///</summary>
///<returns>Generated form field (anti-forgery token).</returns>
public static MvcHtmlString AntiForgeryTokenExtension(this HtmlHelper html)
{
// Call base AntiForgeryToken and save its output to return later.
var output = html.AntiForgeryToken();
// Check that cookie exists
if(HttpContext.Current.Response.Cookies.AllKeys.Contains(AntiForgeryConfig.CookieName))
{
// Set cookie into the variable
var antiForgeryTokenCookie = HttpContext.Current.Response.Cookies.Get(AntiForgeryConfig.CookieName);
// Set cookie configuration
antiForgeryTokenCookie.Path = "/Path";
// antiForgeryTokenCookie.HttpOnly = true;
// ...
}
return output;
}
}
There is a last change that must be done and it is replace AntiForgeryToken() for AntiForgeryTokenExtension() if it is an existing project.
NOTES
With this code you can configure AntiForgeryToken cookie as a normal cookie.
It is also possible to add input parameters to this method, but I am not sure it would be a good practice.
There are different ways to get the cookies but I think that through Response.Cookies is the "most correct", since it is a response cookie.
IMPORTANT
It is needed to check if cookie exist first before trying to get it. If you try to get a Response cookie which doesn't exist, it will be generated. It doesn't happen with Request cookies.
COOKIE KNOWLEDGE
It is not the question itself but explains part of the code and it is quite important to know when we are working with cookies, so I consider it is good to have this information here too.
All Response.Cookies are in Request.Cookies, but not all Request.Cookies are in Response.Cookies.
If you create a Response.Cookie it will appear also in Request.Cookies.
If you create a Request.Cookie it will NOT appear in Response.Cookies.
If you try to get a non-existent cookie from Request.Cookies it will return a null.
If you try to get a non-existent cookie Response.Cookies it will return a new generated cookie.
SOURCES
There is the link where the developers tell to use encapsulation and many other things that could be useful.
Microsoft developers recommendations and information
Source to knowledge of cookies, Request.Cookies and Response.Cookies differences.
Difference between request cookies and response cookies
Difference between request cookies and response cookies 2
Check if cookie exist and difference between kind of cookies
I'm building a plugin for Jenkins and I'm trying to validate my form (connection test method). This worked fine when all #QueryParameter were Strings.
Now I'm trying to send my form validation method an Object like this:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final CredentialsConfig deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final CredentialsConfig resolverCredentialsConfig
) throws ServletException {
In my global.jelly file I have this:
<f:validateButton
title="${%Test Connection}" progress="${%Testing...}"
method="testConnection"
with="url,timeout,bypassProxy,deployerCredentialsConfig,resolverCredentialsConfig"/>
My CredentialConfig class implements Serializable but I guess that is not enough becuase I'm getting this when clicking the "Test Connection" button:
java.lang.IllegalArgumentException: Failed to invoke public hudson.util.FormValidation
org.jfrog.hudson.MyBuilder$DescriptorImpl.doTestConnection(java.lang.String,java.lang.String,boolean,org.jfrog.hudson.CredentialsConfig,org.jfrog.hudson.CredentialsConfig) throws javax.servlet.ServletException
Jenkins has no good documentation for using objects inside of FormValidation calls.
Looking at the Jenkins documentation and the code behind <f:validateButton/>, I believe it's impossible have objects bind in validation logic.
The docs say (https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls):
The 'with' attribute specifies the input fields sent to the server for
the validation. They are matched against the field attribute or the
name attribute of other input controls. The values of the nearest
input fields above the are sent to the server, so
this means the button has to come after the input fields. Multiple
fields can be specified by using ','.
The code simply gets fields by the names - there is no "object assembly" (I believe it's only done during actual config submission).
https://github.com/jenkinsci/jenkins/blob/96ec7a267e0efba2ec99590c871db0940e35920f/war/src/main/webapp/scripts/hudson-behavior.js#L2856
I bumped into a similar problem. Looking at the code, it seems stapler tries to convert your parameter to the type you provided in the doCheck function declaration.
class HandlerImpl extends AnnotationHandler<QueryParameter> {
public Object parse(StaplerRequest request, QueryParameter a, Class type, String parameterName) throws ServletException {
String name = a.value();
if(name.length()==0) name=parameterName;
if(name==null)
throw new IllegalArgumentException("Parameter name unavailable neither in the code nor in annotation");
String value = request.getParameter(name);
if(a.required() && value==null)
throw new ServletException("Required Query parameter "+name+" is missing");
if(a.fixEmpty() && value!=null && value.length()==0)
value = null;
return convert(type,value); // <--- HERE
}
}
As a workaround, I changed the type to boolean, like so:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final boolean deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final boolean resolverCredentialsConfig
) throws ServletException {
This allows me to at least check if the variable is set. It might not be enough for your use case, though.
I'm generating a usertoken like so
public async Task GenerateCode()
{
var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));
}
I then pass the same token into another action via a separate request
public async Task ValidateCode(string code)
{
var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns False
}
However, the response from the VerifyUserTokenAsync method is always false.
If I were to generate the code and verify within the same action
public async Task GenerateCode()
{
var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));
var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns True
}
It returns true.
Why can't the Verify method verify the code in a separate request? Am I missing something obvious?
I finally figured this after pulling my hair out for hours. You need to URL encode the code and I decided to use the HttpUtility class for this.
HttpUtility.UrlEncode(code);
When it comes to verifying the code, you do not need to URL decode the code.
Having just burned 2 days on this issue, here is another reason this might be happening to you.
In your Startup.cs - ConfigureServices(IServiceCollection services) method, ensure that:
services.AddAuthentication
Appears BEFORE
services.AddIdentity
Otherwise calls to VerifyUserTokenAsync will always return false
Cannot solve this problem until haven't used this:
UserManager.VerifyUserTokenAsync(userId, AccountLockedOutPurpose, code).WithCurrentCulture<bool>();
.WithCurrentCulture() - used in all methods such as ResetPasswordAsync etc.)
In my situation I was instantiating a UserManager on demand when one was needed, as opposed to generating one per Owin context in my startup pipeline. Behavior wise, if I validated the token with the same instance of UserManager that created it, it would return true. But if I did an actual forgot password flow where the validation is in a separate request, it was always false.
Switching my setup so that a UserManager was created per owin context resolved the issue for me. Apparently there is some dependency on Owin when it comes to validating tokens.
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Not sure if OP is using .Net Core or not, but if someone comes across this and you're using dependency injection, the solution for me was to scope the UserManager as a singleton.
services.AddSingleton<UserManager<YourUserAccountModel>>();
I believe this is because when the user clicks the confirm email link in their inbox, a new UserManager instance is injected to the controller and does not have the same key that was used to generate the token to begin with. Therefore it cannot verify the token.
For me, I got the same issue. and the solution was very simple.
In my case, I add the purpose with white space like this "Email Confirmation".
the problem was solved when I removed any white space "EmailConfirmation".
bool IsTokenValed = await userManager.VerifyUserTokenAsync(user, userManager.Options.Tokens.EmailConfirmationTokenProvider, "EmailConfirmation", token);
Hi there i am still very new to grails and I have not been able to figure out why this is happening.
I have a domain class:
package scheduler
class Client {
String name
static constraints = {}
}
And a controller:
package scheduler
class AdminController {
def create() {
def client = new Client(name:"John")
println client
}
}
Currently I am always getting null for client. Originally the above was a little more complex on the domain class side but I systematically dumbed it down to see if it was a problem there. I still can not get the above working.
The output is always
scheduler.Client : null
Please let me know if I need to provide anymore information.
It's not null, that's just the default output of the toString method that Grails adds. It prints the class name and the id. Since you haven't saved the instance, the id is null. If the instance was null the output would have been null, not scheduler.Client : null
If you want to see the data in the instance, use the Groovy dump() method, e.g.
def client = new Client(name:"John")
println client.dump()
You could also add a toString method that includes the name attribute, e.g.
package scheduler
class Client {
String name
String toString() { name }
}