appstrax_services 0.0.2 copy "appstrax_services: ^0.0.2" to clipboard
appstrax_services: ^0.0.2 copied to clipboard

outdated

Auth, Database and Storage Services.

@appstrax/services-flutter #

This library contains 4 services:

  • A simple auth service, which allows you to easily integrate appstrax authentication into your applications.
  • A simple database service, which allows you to easily integrate with your appstrax database in your applications.
  • A simple storage service, which allows you to easily integrate appstrax storage into your applications.
  • A simple HTTP service, which allows you to easily integrate HTTP requests into your application.

Getting Started #

Create your Appstrax API's here: https://codecapsules.io/

Installation #

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 #

Models #

// General
FindResult
Message
Tokens
User

// Auth Dto's
LoginDto
RegisterDto
TwoFactorAuthDto
ForgotPasswordDto
ResetPasswordDto
ChangePasswordDto

// Auth Result
AuthStatus
AuthErrors
AuthResult

Auth Service Functions #

// Main functions
appstraxAuth.register();
appstraxAuth.login();
appstraxAuth.forgotPassword();
appstraxAuth.resetPassword();
appstraxAuth.changePassword();
appstraxAuth.saveUserData();
appstraxAuth.logout();

// Auth Functions
appstraxAuth.validateTokens();
appstraxAuth.canRefreshTokens();
appstraxAuth.refreshTokens();
appstraxAuth.onAuthStateChanged();
appstraxAuth.isAuthenticated();

// Email Verification
appstraxAuth.sendEmailVerificationCode();
appstraxAuth.verifyEmailAddress();

// 2fa
appstraxAuth.generateTwoFactorAuthSecret();
appstraxAuth.verifyTwoFactorAuthCode();
appstraxAuth.enableTwoFactorAuth();
appstraxAuth.disableTwoFactorAuthentication();

// Auth Gets
appstraxAuth.getAuthToken();
appstraxAuth.getUser();
appstraxAuth.getAuthStatus();
appstraxAuth.getAuthUrl();
appstraxAuth.getUserId();

User Service Functions #

appstraxUsers.find();
appstraxUsers.findById();
appstraxUsers.findByEmail();

Registration #

import 'package:appstrax_services/auth/auth.dart';

RegisterDto registerDto = RegisterDto(
  email: 'joe@soap.com',
  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) {
  print(err);
  rethrow;
}

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) {
  print(err);
  rethrow;
}

Forgot Password #

ForgotPasswordDto forgotPasswordDto = ForgotPasswordDto(
  email: 'email'
);

try {
  Message message = await appstraxAuth.forgotPassword(forgotPasswordDto);
  print('forgotPassword email sent:  ${message.message}');
} catch (err) {
  print(err);
  rethrow;
}

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) {
  print(err);
  rethrow;
}

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) {
  print(err);
  rethrow;
}

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) {
  print(err);
  rethrow;
}

Users can only update their data if they are already authenticated.

Logout #

try {
  await appstraxAuth.logout():
} catch (err) {
  print(err);
  rethrow;
}

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';
}

Find Users #

Public Availability #

Admin Panel -> Configuration tab -> Public Access -> toggle 'Allow Public Access'

Querying Users #

The find() function takes FetchQuery as an argument

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';
}

Available 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';
}

Add your FetchQuery to the url as queryParams #

  • {baseUrl}/user?where={}&order={}&offset=0&limit=5

Examples #

A query to search for Users:
Where -> email is 'LIKE' 'Joe'
Ascending, ordered by email
Return the first 5

FetchQuery query = FetchQuery(
  // where: {"email":{"LIKE":"Joe"}}
  where: { email: { Operator.LIKE: this.search } },
  // order: {"email": "ASC"}
  order: {},
  offset: 0,
  limit: 5,
);

try {
  FindResult users = await appstraxUsers.find(query: query);
  totalUsers = users.count;
  userData = users.data;
} catch (err) {
  print(err);
  rethrow;
}

A query to search for Users:
Where -> email is 'LIKE' 'Joe'
'OR'
name is 'LIKE' 'Joe'
'OR'
surname is 'LIKE' 'Joe'
No order
Return the first 5

FetchQuery query = FetchQuery(
  // where: {"OR":[{"email":{"LIKE":"cam"}},{"name":{"LIKE":"cam"}},{"surname":{"LIKE":"cam"}}]}
  where: {
    Operator.OR: [
      { email: { Operator.LIKE: this.search } },
      { name: { Operator.LIKE: this.search } },
      { surname: { Operator.LIKE: this.search } },
    ],
  },
  // 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) {
  print(err);
  rethrow;
}

try {
  User user = await appstraxUsers.findById(id);
} catch (err) {
  print(err);
  rethrow;
}

try {
  User user = await appstraxUsers.findByEmail(email);
} catch (err) {
  print(err);
  rethrow;
}

#

Database Service #

Models #

DocumentDto
FindResultDto
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,
  );
}

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,
  });
}

Database Service Functions #

appstraxDb.create();
appstraxDb.findById();
appstraxDb.find();
appstraxDb.edit();
appstraxDb.delete();

Examples #

// 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) {
  print(err);
  rethrow;
}

// 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) {
  print(err);
  rethrow;
}

// 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) {
  print(err);
  rethrow;
}

// 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) {
  print(err);
  rethrow;
}

// 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) {
  print(err);
  rethrow;
}

// delete documents
 try {
  await appstraxDb.delete('testing', createdId as String);
  print('Document deleted.');
} catch (err) {
  print(err);
  rethrow;
}

CRUD Service Functions #

yourService.save();
yourService.findById();
yourService.find();
yourService.delete();

Examples #

// 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();

// 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) {
  print(err);
  rethrow;
}

// The CRUD sevice returns the type created ie: Person
try {
  var foundPerson = await personService.findById(personCreatedId as String);
  print('Person foundById: ${foundPerson.id}');
} catch (err) {
  print(err);
  rethrow;
}

// find
try {
  var foundPersons = await personService.find();
  if (foundPersons != null) {
    for (var per in foundPersons) {
      print('DocId: ${per.id}');
    }
  }
} catch (err) {
  print(err);
  rethrow;
}

// 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) {
  print(err);
  rethrow;
}

#

Storage Service #

Models #

Response

Storage Service Functions #

appstraxStorage.uploadFile();
appstraxStorage.deleteFile();

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) {
  print(err);
  rethrow;
}

// Delete File using downloadUrl
try {
  await appstraxStorage.deleteFile(downloadUrl as String);
  print('Deleted successfully');
} catch (err) {
  print(err);
  rethrow;
}

#

Shared #

Models #

Model
Operator
OrderDirection
FetchQuery

HttpOptions
HttpException
FetchDataException
BadRequestException
UnauthorizedException
// Base Model
abstract class Model {
  String? id;
  DateTime? createdAt;
  DateTime? updatedAt;

  Map<String, dynamic> toJson();
}
0
likes
0
points
28
downloads

Publisher

unverified uploader

Weekly Downloads

Auth, Database and Storage Services.

License

unknown (license)

Dependencies

flutter, http, json_annotation, shared_preferences

More

Packages that depend on appstrax_services