@appstrax/services-flutter
Table of Contents
- Overview
- Getting Started
- Installation
- Setup
- Auth Service
- User Service
- Database Service
- Storage Service
Overview
Appstrax in partnership with CodeCapsules provides software tools and infrastructure to assist in the development, hosting and managing of your applications.
Getting Started
To use these services, instances of the Auth, Database and Storage API's need to be configured internally.
Each instance deploys a front-end to interact with registered users, application data and uploaded Files accordingly.
To get these instances set-up, first send an email to [email protected] and we'll help create, host and manage your Appstrax API's here: https://codecapsules.io/
Installation
Add @appstrax/services
as a project dependency:
pub get @appstrax/services
Setup
Initialize the auth, database & storage
libraries:
// import the services library
import 'package:appstrax_services/services.dart';
// initialize the required services
// you only need to initialize the services you require
await AppstraxServices().init(
authUrl: '', // eg. appstrax-auth-api-snidtu.codecapsules.co.za
databaseUrl: '', // eg. appstrax-database-api-soreuh.codecapsules.co.za
storageUrl: '', // eg. appstrax-storage-api-lsirhc.codecapsules.co.za
);
Auth Service
This library integrates with the Appstrax Auth API which allows you to easily interact with authentication in your mobile applications.
To get started import appstraxAuth
into your project:
import 'package:appstrax_services/auth.dart';
Registration
RegisterDto registerDto = RegisterDto(
email: '[email protected]',
password: '<password>',
data: {
// any additional/custom user fields
'name': 'Joe',
'surname': 'Soap',
...
}
);
try {
AuthResult result = await appstraxAuth.register(registerDto);
User user = result.user!;
print('User Successfully Registered, userId: ${user.id}');
} catch (err) {
// something went wrong while registering the user
handleError(err);
}
Login
LoginDto loginDto = LoginDto(
email: 'email',
password: '<password>',
);
try {
AuthResult result = await appstraxAuth.login(loginDto);
User user = result.user!;
print('User Successfully Logged In, userId: ${user.id}');
} catch (err) {
// something went wrong while logging in
handleError(err);
}
Forgot Password
ForgotPasswordDto forgotPasswordDto = ForgotPasswordDto(
email: 'email'
);
try {
Message message = await appstraxAuth.forgotPassword(forgotPasswordDto);
print('forgotPassword email sent: ${message.message}');
} catch (err) {
// something went wrong sending the email
handleError(err);
}
An email will be sent to the user with a password reset code, this code is only valid for 24 hours.
Reset Password
ResetPasswordDto resetPasswordDto = ResetPasswordDto(
email: 'email',
code: '<code>',
password: '<password>',
);
try {
Message message = await appstraxAuth.resetPassword(resetPasswordDto);
print('Password Successfully Reset: ${message.message}');
} catch (err) {
// something went wrong while resetting the password
handleError(err);
}
The password is now reset, however the user will now need to login with their new password.
Change Password
ChangePasswordDto changePasswordDto = ChangePasswordDto(
password: '<currentPassword>',
newPassword: '<newPassword>',
);
try {
User user = await appstraxAuth.changePassword(changePasswordDto);
print('Changed password for userId: ${user.id}');
} catch (err) {
// something went wrong while changing the password
handleError(err);
}
Users can only change their password if they are already authenticated.
Save User Data/Profile
try {
User updatedUser = await appstraxAuth.saveUserData({
// any additional/custom user fields
'name': 'Joe',
'surname': 'Soap',
'career': 'Software Engineer',
...
});
print('user data successfully updated, userId: ${updatedUser.id}');
} catch (err) {
// something went wrong while updating the user data
handleError(err);
}
Users can only update their data if they are already authenticated.
Logout
try {
await appstraxAuth.logout():
} catch (err) {
// something went wrong while logging out
handleError(err);
}
Auth Error Messages
class AuthErrors {
// registration errors
static const emailAddressAlreadyExists = 'emailAddressAlreadyExists';
static const badlyFormattedEmailAddress = 'badlyFormattedEmailAddress';
static const noPasswordSupplied = 'noPasswordSupplied';
// login errors
static const invalidEmailOrPassword = 'invalidEmailOrPassword';
static const userBlocked = 'userBlocked';
static const invalidTwoFactorAuthCode = 'invalidTwoFactorAuthCode';
// forgot/reset password errors
static const emailAddressDoesNotExist = 'emailAddressDoesNotExist';
static const invalidResetCode = 'invalidResetCode';
// unknown errors
static const unexpectedError = 'unexpectedError';
}
User Service
This library integrates with the Appstrax Auth API which allows you to easily manage the users in your mobile applications.
To get started import appstraxUsers
into your project:
import 'package:appstrax_services/auth.dart';
Public Availability
Admin Panel -> Configuration tab -> Public Access -> toggle 'Allow Public Access'
Querying Users
The appstraxUsers.find()
function takes a FetchQuery as an argument and returns a FindResultDto
Examples
A query to search for the users
table similar to:
SELECT * FROM users WHERE email LIKE '%Joe%' ORDER BY email ASC LIMIT 5
FetchQuery query = FetchQuery(
// where: {"email":{"LIKE":"Joe"}}
where: { email: { Operator.LIKE: 'Joe' } },
// order: {"email": "ASC"}
order: {},
offset: 0,
limit: 5,
);
try {
FindResult users = await appstraxUsers.find(query: query);
totalUsers = users.count;
userData = users.data;
} catch (err) {
// something went wrong while querying the users
handleError(err);
}
A query to search for the users
table similar to:
SELECT * FROM users WHERE email LIKE '%Joe%' OR name LIKE '%Joe%' OR surname LIKE '%Joe%' LIMIT 5
FetchQuery query = FetchQuery(
// where: {"OR":[{"email":{"LIKE":"cam"}},{"name":{"LIKE":"cam"}},{"surname":{"LIKE":"cam"}}]}
where: {
Operator.OR: [
{ email: { Operator.LIKE: 'Joe' } },
{ name: { Operator.LIKE: 'Joe' } },
{ surname: { Operator.LIKE: 'Joe' } },
],
},
// order: {"email":"ASC"}
order: {"email": OrderDirection.ASC},
offset: 0,
limit: 5,
);
try {
FindResult users = await appstraxUsers.find(query: query);
totalUsers = users.count;
userData = users.data;
} catch (err) {
// something went wrong while querying the users
handleError(err);
}
try {
User user = await appstraxUsers.findById(id);
} catch (err) {
// something went wrong while querying the users
handleError(err);
}
try {
User user = await appstraxUsers.findByEmail(email);
} catch (err) {
// something went wrong while querying the users
handleError(err);
}
Database Service
This library integrates with the Appstrax Database API which allows you to easily interact with your database in your mobile applications.
To get started import appstraxDb
into your project:
import 'package:appstrax_services/database.dart';
Create
// Create a new Document, returns a DocumentDto from the 'testing' collection
try {
var document = await appstraxDb.create('testing', {
'name': 'John',
'surname': 'Doe',
'dogs': 3,
'career': 'Software Engineer',
});
createdId = document.id;
print('Document created docId: $createdId');
} catch (err) {
// something went wrong while creating
handleError(err);
}
Edit
// edit documents
try {
var document = await appstraxDb.edit('testing', createdId, {
'name': 'John',
'surname': 'Doe',
'dogs': 3,
'career': 'Senior Software Engineer',
'added': 'this field'
});
print('Document edited: ${document.id}');
} catch (err) {
// something went wrong while editing
handleError(err);
}
Delete
// delete documents
try {
await appstraxDb.delete('testing', createdId as String);
print('Document deleted.');
} catch (err) {
// something went wrong while deleting
handleError(err);
}
Find By Id
// findById returns a DocumentDto from the 'testing' collection
try {
var document = await appstraxDb.findById('testing', createdId as String);
print('Document foundById: ${document.id}');
} catch (err) {
// something went wrong while querying the 'testing' collection
handleError(err);
}
Find
// find returns a FindResultDto<DocumentDto>
try {
var documents = await appstraxDb.find('testing');
if (documents.data?.length != null) {
documents.data?.forEach((user) {
print('docId: ${user.id}');
});
}
} catch (err) {
// something went wrong while querying the 'testing' collection
handleError(err);
}
// find accepts a FetchQuery as in examples above
// You can create compound queries
// Here we search for documents where name=='John' AND dogs IN [1, 5, 7, 2]
try {
FindResultDto<DocumentDto> documents = await appstraxDb.find(
'testing',
query: FetchQuery(
where: {
Operator.and: [
{
'name': {Operator.equal: 'John'}
},
{
'dogs': {
Operator.qIn: [1, 5, 7, 2]
}
},
]
},
order: {"email": OrderDirection.ASC},
offset: 0,
limit: 5,
),
);
if (documents.data?.length != null) {
documents.data?.forEach((user) {
print('docId: ${user.id}');
});
}
print('Documents found using find(query)');
} catch (err) {
// something went wrong while querying the 'testing' collection
handleError(err);
}
CRUD Service
The CrudService
is a abstract class which wraps the Create, Read, Update and Delete functions in appstraxDb
. The CrudService
is declared with a model which extends the Model
class, this model is the type that the service Creates, Reads, Updates and Deletes.
Similarly to appstraxDb
, the CrudService
uses a collection name which represents the "table" that the data is stored in on the server.
To get started import CrudService & Model
into your project:
import 'package:appstrax_services/database.dart';
Create your custom Model & Service
:
// Create a custom Model that implements the base Model
import 'package:json_annotation/json_annotation.dart';
import 'package:appstrax_services/shared/models/model.dart';
part 'person.g.dart';
@JsonSerializable()
class Person implements Model {
@override
String? id;
@override
DateTime? createdAt;
@override
DateTime? updatedAt;
String name;
String surname;
String career;
int dogs;
Person({
this.id,
this.createdAt,
this.updatedAt,
required this.name,
required this.surname,
required this.career,
required this.dogs,
});
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
@override
Map<String, dynamic> toJson() => _$PersonToJson(this);
}
// Generate your person.g.dart file from the terminal with:
flutter pub run build_runner build
// Create a custom service for the Model that extends the CRUD service
class PersonService extends CrudService<Person> {
PersonService() : super('person', Person.fromJson);
}
var personService = PersonService();
We can now use the ProfileService
as follows:
// Now you have access to all the CRUD functions on your personService
try {
Person person = Person(
name: 'James',
surname: 'Doe',
career: 'farmer',
dogs: 9,
);
// save checks for an ID, if it exists the doc is edited else it is created
var createdPerson = await personService.save(person);
personCreatedId = createdPerson.id;
print('Person created: ${createdPerson.id}');
} catch (err) {
// something went wrong while saving
handleError(err);
}
// The CRUD service returns the type created ie: Person
try {
var foundPerson = await personService.findById(personCreatedId as String);
print('Person foundById: ${foundPerson.id}');
} catch (err) {
// something went wrong while querying
handleError(err);
}
// find
try {
var foundPersons = await personService.find();
if (foundPersons != null) {
for (var per in foundPersons) {
print('DocId: ${per.id}');
}
}
} catch (err) {
// something went wrong while querying
handleError(err);
}
// The find() accepts a FetchQuery, same as above
try {
var foundPersons = await personService.find(
query: FetchQuery(where: {
'name': {Operator.equal: 'James'}
}),
);
if (foundPersons != null) {
for (var per in foundPersons) {
print('DocId: ${per.id}');
}
}
} catch (err) {
// something went wrong while querying
handleError(err);
}
Storage Service
This library integrates with the Appstrax Storage API which allows you to easily interact with storage in your mobile applications.
To get started import appstraxStorage
into your project:
import 'package:appstrax_services/storage.dart';
Examples
// Upload File
try {
Response res = await appstraxStorage.uploadFile(file, '<folder>/',
options: HttpOptions(
onUploadProgress: (progress) => print(
'Upload Progress: ${progress.percent}',
),
));
downloadUrl = res.downloadUrl;
print('DownloadUrl: ${res.downloadUrl}');
} catch (err) {
// something went wrong while uploading
handleError(err);
}
// Delete File using downloadUrl
try {
await appstraxStorage.deleteFile(downloadUrl as String);
print('Deleted successfully');
} catch (err) {
// something went wrong while deleting
handleError(err);
}
Query Models
The find()
function accepts FetchQuery
as an argument:
Fetch Query
class FetchQuery {
// Conditions to query data
Map<String, dynamic>? where;
// ASC, DESC Order
Map<String, dynamic>? order;
// Pagination variables
int? offset;
int? limit;
}
class OrderDirection {
// Ascending Order Direction
static const asc = 'ASC';
// Descending Order Direction
static const desc = 'DESC';
}
Query Operators
class Operator {
// Equal To Operator
static const String equal = 'EQUAL';
// Not Equal To Operator
static const String notEqual = 'EQUAL';
// And Operator
static const String and = 'AND';
// Or Operator
static const String or = 'OR';
// Greater Than Operator
static const String gt = 'GT';
// Greater Than or Equal To Operator
static const String gte = 'GTE';
// Less Than Operator
static const String lt = 'LT';
// Less Than or Equal To Operator
static const String lte = 'LTE';
// Like Operator
static const String like = 'LIKE';
// Not Like Operator
static const String notLike = 'NOT_LIKE';
// In Operator
static const String qIn = 'IN';
}
Query Results
The find()
function returns a FindResultDto
:
// querying the data returns a FindResultDto<DocumentDto> from the collection
class FindResultDto<T extends DocumentDto> {
List<DocumentDto>? data;
dynamic where;
dynamic order;
int? limit;
int? offset;
int? count;
FindResultDto({
this.data,
this.where,
this.order,
this.limit,
this.offset,
this.count,
});
}
class DocumentDto {
final String id;
final Map<String, dynamic> data;
final DateTime createdAt;
final DateTime updatedAt;
DocumentDto(
this.id,
this.data,
this.createdAt,
this.updatedAt,
);
}
Libraries
- auth/services/appstrax_auth
- database/services/appstrax_database
- services
- storage/services/appstrax_storage
- auth/services/appstrax_users
- auth/auth
- auth/models/auth_dtos
- auth/models/auth_result
- database/services/crud.service
- database/database
- database/models/document_dto
- auth/models/find_result
- database/models/find_result_dto
- shared/http/http
- shared/models/http_exception
- auth/models/message
- shared/models/model
- shared/http/multipart_request
- shared/preferences/preferences_service
- shared/models/query
- storage/models/response
- storage/storage
- auth/models/tokens
- auth/models/user
- shared/utils