simple question here but wondering if anyone can offer the right solution.
I want to take in an object of the same type as my current class, and set all my fields to that object's fields, without individually setting each out. Is there a way to do that easily or no?
Eg.,
User({required this.uid}) {
Database().getUser(uid).listen((User user) async {
displayName = user?.displayName;
email = user?.email;
phoneNumber = user?.phoneNumber;
photoURL = user?.photoURL;
notifyListeners();
});
}
The above works but isn't clean.
I want to be able to do the above in 1 line, eg., set
this.user = user
Not sure if this is possible. Thanks!
Related
I am struggling to reference specific things in my firebase real time database. I understand that when you want to read something specific from the database you need to specify the exact path where the item can be found.
If you see the screenshot attached, I want a way to read the name of each menuItem and store them in a list.
It seems like this can only be done if you reference each menuItem ID individually in the path (like in the code below).
Is there not a way to say ("menuItem/itemID/itemName") so that I can access each menuItem name dynamically using a for loop with a terminating value equal to the number of menu items in the database?
Any help would be greatly appreciated!
final DatabaseReference _dbRef = FirebaseDatabase.instance.ref();
late DataSnapshot _itemStream;[![enter image description here][1]][1]
Future<List<String>> _readItemNames() async {
_itemStream = await _dbRef.child("menuItem/J1/itemName").get();
itemName = _itemStream.value.toString();
itemNames.addAll([itemName]);
_itemStream = await _dbRef.child("menuItem/J2/itemName").get();
itemName = _itemStream.value.toString();
itemNames.addAll([itemName]);
return itemNames;
}
If you want to read and process all menu items, you can do:
var snapshot = await _dbRef.child("menuItem").get();
snapshot.children.forEach((childSnapshot) {
var props = childSnapshot.val() as Map;
print(props["itemName"]);
});
For more on this, see the Firebase documentation on reading a list of items with a value event (you're just using get() instead of onValue, but the logic is the same).
There is no way to get only the itemName property of each child node, so if all you need it the names you're loading more data than needed. If that is a concern, consider creating an additional list with just the value(s) you need. For example:
menuItemNames: {
"J1": "Milk Shake",
"J10": "Name of J10",
...
}
I am trying to get the most recent ID of from my orders table to that I can then use this ID in a path to get the order number and increment it by one.
void _activateListeners() {
final recentOrder = _readRef.child('Orders').limitToLast(1).get();
final readOrder = _readRef
.child('Orders/{$recentOrder}/orderNum')
.onValue
.listen((event) {
final orderNum = event.snapshot.value;
setState(() {
lastOrderNum = orderNum.toString();
intOrderNum = int.parse(lastOrderNum) + 1;
newOrderNum = intOrderNum.toString();
});
});
}
I know that I need to use the "key" word somehow but I have been unable to solve this problem.
my database table looks as follows:
Orders
-N3ZdY6LOL_9Z-6KXHnK
*cartProduct
*dateTime:"2022-06-02 15:41:20.470139"
*orderNum:"6"
*totalAmount:45
-N3ZdgEQIzsjLA5NCu3U
*cartProduct
*dateTime:"2022-06-02 15:41:20.470139"
*orderNum:"7"
*totalAmount:45
Edit: can someone tell me if it is even possible to fetch the unique push ID after it has been made (not directly after the order is added)? I have looked at all the documentation and I have failed to implement anything. I have also found numerous similar questions that are either just different or unanswered.
If I know SQL is SQLite a better alternative?
You can get the key from the snapshot by using the snapshot's key property, like in this line below:
String? eventKey = event.snapshot.key;
Check out the documentation for Flutter's Realtime Database's DataSnapshot class for more information.
this function takes a ServicePoint object as argument, which has the following attributes:
adminId (String)
name (String)
serviceType (enum)
I want this function to create a new Table with name: "name+adminId". This is achieved.
Also I want this function to create a new Table (if it is not there already) by the name ServicePoints.
ServicePoints stores the relationship between user (with objectId = adminId) and the new Table.
To achieve this, I set "serviceTable" attribute with value as the new Table created, acting as a pointer.
When I run the code first time, I achieve the required tables. But, when I run the function second time, it doesn't add the new row/record to ServicePoints table.
I don't know why.
UPDATE I found that set ParseObject operation is the culprit. But, to my surprize, it executes successfully for the very first time. But fails every next time. This is really absurd behaviour from parse_server_sdk_flutter.
Future<bool> createServicePoint(ServicePoint servicePoint) async {
String newServicePointName = servicePoint.name + servicePoint.adminId;
var newServiceTable = ParseObject(newServicePointName);
var response = await newServiceTable.save();
if (response.success) {
print('Now adding new row to ServicePoints table');
var servicePointsTable = ParseObject('ServicePoints')
..set<String>("serviceName", servicePoint.name)
..set<String>("adminId", servicePoint.adminId)
..set<String>("serviceType", _typeToLabel[servicePoint.serviceType])
..set<ParseObject>("serviceTable", newServiceTable);
var recentResponse = await servicePointsTable.save();
return recentResponse.success;
} else {
return false;
}
}
If anyone runs into this problem, you need to check the result after saving the ParseObject. If there is error like "Can't save into non-existing class/table", then just go to the dashboard and create the table first.
So I am writing a Blazor webassembly application, with asp.ner core Identity. I need to get the ID of the current user, not the username that the methods in Identy give.
The method
Context. User.identity.name
gives the username but I need the ID for a fk in a model/table.
I can't use the username as usernames might change.
I have searched the net, however I keep seeing just the username returned.
Any assistance will be greatly appreciated.
I use this with the boiler plate Identity Server:
#page "/claims"
#inject AuthenticationStateProvider AuthenticationStateProvider
<h3>ClaimsPrincipal Data</h3>
<p>#_authMessage</p>
#if (_claims.Count() > 0)
{
<table class="table">
#foreach (var claim in _claims)
{
<tr>
<td>#claim.Type</td>
<td>#claim.Value</td>
</tr>
}
</table>
}
<p>#_userId</p>
#code {
private string _authMessage;
private string _userId;
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
protected override async Task OnParametersSetAsync()
{
await GetClaimsPrincipalData();
await base.OnParametersSetAsync();
}
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
_authMessage = $"{user.Identity.Name} is authenticated.";
_claims = user.Claims;
_userId = $"User Id: {user.FindFirst(c => c.Type == "sub")?.Value}";
}
else
{
_authMessage = "The user is NOT authenticated.";
}
}
}
In Startup.cs, add the following line in ConfigureServices
services.AddHttpContextAccessor();
In your Blazor component, add the following lines on the top of the file
#using System.Security.Claims
#inject IHttpContextAccessor HttpContextAccessor
In your method, add the following lines to get the UserId
var principal = HttpContextAccessor.HttpContext.User;
var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
Not an answer, just a tip on using breakpoints to find the answer. My site is Blazor Server, so it's very possible that things are different-- in my case, Brian Parker's solution didn't work for me, so I did the following:
var user = (await AuthenticationStateProvider.GetAuthenticationStateAsync()).User;
if (true) {} // or any other code here, breakpoint this line
If you set a breakpoint right after retrieving the user, run the app and hover the user variable in the code when it breaks, it will pop up the complete object. By hovering various fields, you can investigate. I found that the claim type strings were big long things like "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
So the answer that worked for me was:
var user = (await AuthenticationStateProvider.GetAuthenticationStateAsync()).User;
string userId = user.FindFirst(c => c.Type.Contains("nameidentifier"))?.Value;
My point is that when the docs are complicated, or when the technology is changing fast so that one day's right answer is the next day's wrong lead, you can achieve a lot just by using VS to dig around.
Hope that helps someone. :D
I have installed the IS3/MR/IDM combination and everything is working fine. What I need to do now is make the the logged in user (ID, Name etc) available to all my MVC controllers so the obvious choice is to create a base controller so all others controllers inherit from it.
Could anyone advise if this is the best way to achieve this and perhaps provide some sample code?
Assuming you are already successfully authenticating against Identity Server 3, you should be all set already. If you look in the CallApiController you'll find this method
// GET: CallApi/UserCredentials
public async Task<ActionResult> UserCredentials()
{
var user = User as ClaimsPrincipal;
var token = user.FindFirst("access_token").Value;
var result = await CallApi(token);
ViewBag.Json = result;
return View("ShowApiResult");
}
the user variable should already contain claims for the user's name, Id and such. So
var id = user.FindFirst(Constants.ClaimTypes.Subject).Value;
var firstName = user.FindFirst(Constants.ClaimTypes.GivenName).Value;
var middleName = user.FindFirst(Constants.ClaimTypes.MiddleName).Value;
var lastName = user.FindFirst(Constants.ClaimTypes.LastName).Value;
Of course, that all assumes that you've got that information in your store of user information and I'm not checking for the errors that will occur if they are not there.