appwrite list users search params - flutter

I am trying to use appwrite server sdk list users to get userid from an email.
The documentation says there is a search: option that can be used but no where does it say what the format of that String? is.
What is the format of the search: String? to only get a list of users whose email matches?
void main() { // Init SDK
Client client = Client();
Users users = Users(client);
client
.setEndpoint(endPoint) // Your API Endpoint
.setProject(projectID) // Your project ID
.setKey(apiKey) // Your secret API key
;
Future result = users.list(search: '<<<WHAT GOES HERE>>>');
}

:wave: Hello!
Thanks for bringing this question up, this is definitely not well documented, I'll note this down and try to make it clearer in the docs, but here's how you'd approach this in Dart:
final res = users.list(search: Query.equal('email',
'email#example.com'));
res.then((response) {
print(response.users[0].toMap());
}).catchError((error) {
print(error);
});
The Query object generates a query string, and works similar to how listDocument would work. The difference here is that it only takes a single query string instead of a list.

Related

Flutter async rest api call in synchronised way

I have an API to fetch results based on some user typed text. I want api calls to run in syncronized way so last API call result should be in last.
Use case
User type #cbc
API is calling 4 time
#, #c, #cb and #cbc
Issue is API result is giving result randomly not in syncronized way.
Future<void> getHashtags(String tagName) async {
var params = jsonEncode(
{"tag_name": tagName, "latest_hashtag_community": true});
var response = await _postRepository.getHashTags(params,
pageNo: pageNumberHashtags);
}

Cannot convert JSON into Objects

i All,
The Project: A handy utility for tickets at work to help sort and manage my tickets, built on top of our provider's API.
My Background: I'm like 19 hours total into dart and am almost done with my first bootcamp.
The GIST: I have started writing a provider for our helpdesk software's API. I am sending requests to the API successfully but I am utterly clueless on transforming the data into an actual map to generate ticket instances with.
What I'm trying to accomplish:
Fetch the data from the API
Convert that String into a MAP of json objects that I can iterate
through
Iterate through the JSON objects to create instances of ticket
objects with
build a list of those ticket objects and return it to requestor to
generate a widget list.
I could swear I've done everything reasonable to try and type cast this as a map but I think there is something I just don't understand. FWIW I think whatever it is I'm trying to do is accessing a Future not the actual data. and I think i might be confused or unclear about async/awaits but my understanding of the code I've written is that the actions are chained one to another so I shouldn't be "waiting" for anything or getting a future, I should just be getting a string.
Otherwise, Here's my code cleaned up, any advice or suggestions on working with the data in the print would be much appreciated.
class ticketingsoftwareAPIProvider {
// Object Properties
Client _client = Client();
final String _ApiKey = "YOUSHALLPASS!";
final String apiRoot = "https://api.ticketingsoftware.com";
final String agentId = '2675309';
getAgentTickets() async {
// Headers for our HTTP Request
Map<String, String> headers = {
'X-ticketingsoftware-Authorization': 'Bearer $_ApiKey',
'Accept': 'application/vnd.ticketingsoftware.v2.1+json',
'Content-Type': 'application/json'
};
await _client
.get(Uri.parse('$apiRoot/incidents.json?assigned_to=$agentId'))
.then((data) {
if (data.statusCode == 200) {
print(json.decode(data.body));
// CANT SEEM TO MAKE THIS A INTO A MAP TO GENERATE OBJECTS WITH.
}
});
}
}
} // END CLASS
I apologize for any missing information, I am new to dart and REALLY programming in general and am still learning the culture. please let me know if there is any additional information that might help.
My Solution ended up being:
List ticketJson = json.decode(data.body);
for (var ticket = 0; ticket < ticketJson.length; ticket++) {
thisAgentsTickets.add(incident.fromJson(ticketJson[ticket]));
return thisAgentsTickets;
I think I've been learning from a very out of date course.
You need fromJson method to convert it to an object. For example
if (data.statusCode == 200) {
return AgentTicket = AgentTicket.fromJson(data.body)
}
Use json_serializable package for easy way to create the method, or you can create it manually too.

Flutter authentication with email and password without using Firebase

Is it possible to achive authentication with email and password in flutter without using firebase? I have searched around Stackoverflow and internet in general and found nothing about this.
I am creating a simple authentication class this is what I have done at the moment:
class User {
bool isAuthenticated = false;
late String userid;
late String username;
late String email;
late DateTime expireDate; // this variable is used to make the user re-authenticate when today is expireDate
User(bool isAuthenticated, String userid, String username, String email) {
this.isAuthenticated = isAuthenticated;
this.userid = userid;
this.username = username;
this.email = email;
this.expireDate = new DateTime.now().add(new Duration(days: 30));
}
}
class Authentication {
Future<User> signin(String email, String password) {}
void signup(String username, String email, String password) {}
}
EDIT #1: I know how to setup a cookie/token based authentication server I have my own repos on that topic: cookie authentication, token authentication but I don't know how to handle the tokens/cookies in flutter.
This answer is based of #edit1. Since you mentioned that you already know how to set up tokens on the server side you're half way done. Here's a few assumptions I'm making, you already know js/php and worked with JSON output, The database already has a column and table that keeps track of sessions and user_id.
Since you know how Cookies are built this should be relatively easy cause i built it around similar architecture. We has to use the local memory that app's provide access to. There are two packages in flutter that allow u to do this, you can use either:
shared_preferences package link
flutter_secure_storage package link
The main difference is if you want to store 'tokens' or data you want secure you would obviously use flutter_secure_storage. I'm going to use this for code example. And yes the data is saved even after the app is closed.
Setting up Tokens(flutter):
Setting up User Class
When using firebase we generally take for granted the user class that comes with flutter_auth but that is basically what we have to build. A user class with all the data u want to store and then a function called authenticate.
class AppUser{
final _storage = new FlutterSecureStorage();
//below class is mentioned in the next part
AuthApi api = new AuthApi();
//constructor
AppUser(){
//ur data;
};
Future<bool> authenticate(email, password) async {
//this is the api mentioned in next part
http.Response res = await api.login(email, password);
Map<String, dynamic> jsonRes = jsonDecode(res.body);
if (jsonRes["error"]) {
return false;
}
_setToken(jsonRes["token"]);
_setUID(jsonRes["user-id"].toString());
_setAuthState(true);
return true;
}
Future<void> _setToken(String val) async {
//how to write to safe_storage
await _storage.write(key: 'token', value: val);
}
Future<void> _setUID(String val) async {
await _storage.write(key: 'user_id', value: val);
}
//you can stream this or use it in a wrapper to help navigate
Future<bool> isAuthenticated() async {
bool authState = await _getAuthState();
return authState;
}
Future<void> _getAuthState() async {
//how to read from safe_storage u can use the same to read token later just replace 'state' with 'token'
String myState = (await _storage.read(key: 'state')).toString();
//returns boolean true or false
return myState.toLowerCase() == 'true';
}
Future<void> _setAuthState(bool liveAuthState) async {
await _storage.write(key: 'state', value: liveAuthState.toString());
}
}
and assuming ur going to authenticate on a button press so it would look like
onPressed(){
AuthUser user = new AuthUser();
if(user.authenticate(email, password)){
//if logged in. Prolly call Navigator.
}else{
//handle error
}
}
Setting up api calls
Oka so this is calling a Node express API, and the json output looks like
//if successful
{"status":200, "error": false, "token": "sha256token", "user-id": "uid"}
we need to create a class that will give us an output for making this call hence the AuthApi class
class AuthApi {
//this is the login api and it returns the above JSON
Future<http.Response> login(String email, String password){
return http.post(
Uri.parse(ip + '/api/auth/login'),
headers: <String, String>{
'Content-Type': 'application/json',
},
body: jsonEncode(<String, String>{
"email": email,
"password": password,
}),
);
}
}
Thank you for clarifying what u needed, it helped answer better.
You can use Nodejs & express to create your own API and MongoDB or any other DB to act as a persistent DB. I am attaching my github repo link which has minimum code required to setup a email/password auth in mongodb
Github
EDIT :
I have little to no idea about sessions but for tokens there are packages in pub.dev which lets you decode the tokens. jwt-decoder.
You can check the expiry time of the token using this package and for storing them you can use secure_storage
I had a look at your token authentication repo. I would suggest you to verify the token when you get them and not just blindly trust them.
Yes it is Totally possible to create Authentication without Firebase, but it becomes a-lot more difficult and there are multiple solutions.
What firebase provides:
Server space with no down time
Complete set of Api's including authentication with various methods
Strong security(built by google)
Ease of use and setup with great documentation
The reason I bring these up is cause the alternative ur looking for is very difficult for a programer who's relatively new and can feel like you are building multiple applications at a time. It's definitely a learning curve. Also I'm assuming u don't just want local authentication cause thats kinda pointless.
Creating ur own backend involves:
Setting up a server(usually ubuntu)(and either on a raspi or a host like amazon, digital ocean, etc)
Setting up a database with tables(mysql, sql, mongoDB)
Creating communication API's (php, Node.js)
So here's what i'd recommend for getting into backend dev,
use LAMP architecture : Linux, Apache, MySQL, PHP
Setting up Lamp isn't too hard heres a link i followed:
https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-16-04
After u set up ur back end, then u have to create api calls from flutter.
The call (if u created an auth.php where people can login) would look something like:
http://ip:8080/auth.php?email="example#gmail.com"&pass="123456"
I understand why you feel like you didn't find solutions, i was there too but there are tons,LAMP is one of the more easier ones. If u are still interested i'd recommend checking out System Design courses.

Parse Server SDK - Include Object method doesn't work for fetching the whole object in flutter

I was using parse server sdk in my app for database.
I have three class in my Back4App Dashboard which are "_User", "Office", "Office_Members".
In Office_Members class it has following columns,
user_id (Pointer to _User)
office_id (Pointer to Office)
count
To fetch the data including Pointer to _User as well from Office_Members, I am using following code,
QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject("Office_Members"))
..whereEqualTo("office_id", ParseResponse_OfficeObject)
..includeObject(["user_id "]);
ParseResponse apiResponse = await parseQuery.query();
Output :
Payload : [{"className":"Office_Members","objectId":"twpDY51PUK","createdAt":"2020-08-14T09:58:59.775Z","updatedAt":"2020-08-14T09:58:59.775Z","office_id":{"__type":"Pointer","className":"Office","objectId":"4dkfSMrwBI"},"user_id":{"__type":"Pointer","className":"_User","objectId":"Hx5xJ5ABxG"},"count":1}]
In my payload response i am not getting whole user_id pointer response.
So can anybody help me that what i might be doing wrong?
Thanks.
The data should be included.
The logging function simply does not print the data of pointers.
The data should be included. The print function not print the data of pointers.
You can print it out directly for testing purposes, E.g.
response.results[0].get('user_id').get('name')
Evaluation Expression E.g.
In your model u can access at same way, E.g
Call Model
if(response.success){
return response.results.map((p) => Example.fromParse(p)).toList();
} else {
throw ParseErrors.getDescription(response.error.code);
}
Model
import 'package:parse_server_sdk/parse_server_sdk.dart';
class Example {
Example({this.id, this.name});
Example.fromParse(ParseObject parseObject) :
id = parseObject.objectId,
name = parseObject.get('user_id').get('name');
final String id;
final String name ;
#override
String toString() {
return 'Example{id: $id, name: $name}';
}
}
Why not simply use cloud code ? I'm not to familiar with flutter but I can suggest you this alternative solution.
Write a function like this.
Parse.Cloud.define("fetchMemberAndUser", async (request) => {
//Pass in ParseResponse_OfficeObject ID as parameter
var objectId = request.params.id;
//Now do a simple get query
var query = new Parse.Query(Parse.Object.extend("Office_Members"));
//Using .includes to get the user profile object
query.include("user_id");
//This will return Office_Memebers Object along with user profile
return query.get(objectId,{useMasterKey:true});
}

How to construct a REST API that takes an array of id's for the resources

I am building a REST API for my project. The API for getting a given user's INFO is:
api.com/users/[USER-ID]
I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?
If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.
RESTful attempt:
POST http://example.com/api/batchtask
[
{
method : "GET",
headers : [..],
url : "/users/id1"
},
{
method : "GET",
headers : [..],
url : "/users/id2"
}
]
Server will reply URI of newly created batchtask resource.
201 Created
Location: "http://example.com/api/batchtask/1254"
Now client can fetch batch response or task progress by polling
GET http://example.com/api/batchtask/1254
This is how others attempted to solve this issue:
Google Drive
Facebook
Microsoft
Subbu Allamaraju
I find another way of doing the same thing by using #PathParam. Here is the code sample.
#GET
#Path("data/xml/{Ids}")
#Produces("application/xml")
public Object getData(#PathParam("zrssIds") String Ids)
{
System.out.println("zrssIds = " + Ids);
//Here you need to use String tokenizer to make the array from the string.
}
Call the service by using following url.
http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76
where
http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
As much as I prefer this approach:-
api.com/users?id=id1,id2,id3,id4,id5
The correct way is
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
or
api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5
This is how rack does it. This is how php does it. This is how node does it as well...
There seems to be a few ways to achieve this. I'd like to offer how I solve it:
GET /users/<id>[,id,...]
It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.
I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).
I'm interested in comments in my hunt for the ideal solution to this form :)
You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON.
An example controller function would be:
public JsonpResult GetUsers(string userIds)
{
var values = JsonConvert.DeserializeObject<List<int>>(userIds);
var users = _userRepository.GetAllUsersByIds(userIds);
var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
var result = new { users = collection };
return this.Jsonp(result);
}
public IQueryable<User> GetAllUsersByIds(List<int> ids)
{
return _db.Users.Where(c=> ids.Contains(c.Id));
}
Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.
function GetUsers()
{
var link = '<%= ResolveUrl("~")%>users?callback=?';
var userIds = [];
$('#multiselect :selected').each(function (i, selected) {
userIds[i] = $(selected).val();
});
$.ajax({
url: link,
traditional: true,
data: { 'userIds': JSON.stringify(userIds) },
dataType: "jsonp",
jsonpCallback: "refreshUsers"
});
}