play2-auth don't recognize user after login - authentication

I'm trying to implement a login with play2-auth and playframework 2.2.0, I implemented the logic from the last branch using async, after a success login the Home action don't recognize the logged user and redirect to login again, some code:
The AuthConfig trait:
trait AuthConfigImpl extends AuthConfig {
type Id = String
type User = Account
type Authority = models.poso.Permission
val idTag: ClassTag[Id] = classTag[Id]
val sessionTimeoutInSeconds: Int = 3600
def resolveUser(id: Id)(implicit ctx: ExecutionContext): Future[Option[User]] = Future.successful(Cache.getAccountJson(id))
def loginSucceeded(request: RequestHeader)(implicit ctx: ExecutionContext): Future[SimpleResult] =
Future.successful(Redirect(routes.Home.test))
def logoutSucceeded(request: RequestHeader)(implicit ctx: ExecutionContext): Future[SimpleResult] =
Future.successful(Redirect(routes.Login2.login))
def authenticationFailed(request: RequestHeader)(implicit ctx: ExecutionContext): Future[SimpleResult] =
Future.successful(Redirect(routes.Login2.login))
def authorizationFailed(request: RequestHeader)(implicit ctx: ExecutionContext): Future[SimpleResult] =
Future.successful(Forbidden("no permission"))
def authorize(user: User, authority: Authority, request: RequestHeader)(implicit ctx: ExecutionContext): Future[Boolean] = Future.successful {
val perm = user.user.permissao.tree.get(request.path).getOrElse(false)
perm match {
case true => true
case _ => false
}
}
}
The Home action:
class Home #Inject() (implicit sessionService: SessionService) extends Controller with AuthElement with AuthConfigImpl {
def test() = StackAction(AuthorityKey -> NormalUser) { implicit request =>
{
val u = loggedIn
//usurio tem permissao
Ok(views.html.home(u.user.email.toString))
// Ok(views.html.home(user.get.email.toString))
}
}
}
The login class:
class Login2 #Inject() (implicit sessionService: SessionService, loginService: LoginService, userService: UserService) extends Controller with LoginLogout with AuthConfigImpl with Logging {
def authenticate = Action.async { implicit request =>
{
val form = userForm.bindFromRequest
try {
form.fold(
errors => {
Future.successful(BadRequest(views.html.login("", userForm)))
},
other1Form => {
val login = loginService.loginVerify(other1Form.email, other1Form.password)
val uuidGenerate = java.util.UUID.randomUUID.toString
val account = userService.getDataFromUser(other1Form.email)
Cache.addEntry(EhCacheRegion.Cerberus.toString() + SessionProductName.Account.toString(), uuidGenerate, models.poso.Session.toJson(account))
gotoLoginSucceeded(uuidGenerate)
})
} catch {
case login: LoginException => {
val formError = form.withGlobalError(login.msg)
Future.successful(BadRequest(views.html.login("", formError)))
}
case ex: Exception => {
logger.error(ex.getMessage())
Future.successful(BadRequest(views.html.login("", form.withGlobalError("system error"))))
}
case _: Any => {
logger.error("error")
Future.successful(BadRequest("err"))
}
}
}
}
}
this is the result on browser:

Make sure that you don't have secure cookies set, and try to test in an unsecured environment.
Check AuthConfig, for lazy val cookieSecureOption

Related

suspend function testing with spock

I have a simple function in kotlin like that :
suspend fun createTicket(#Valid request: CreateTicketRequest, authentication: Authentication): HttpResponse<Any> {
request.customerId = "customerId"
logger().info("Receive by the client $request")
return HttpResponse.created(service.create(request))
}
I've already Mock the request and the authentication.
So, I call it on Spock:
def 'It should create a ticket with success'() {
given:
def request = createRequest(
TICKET_ID,
TICKET_NAME,
TICKET_PHONE,
TICKET_CPF,
TICKET_EMAIL,
TICKET_COMMENT,
TICKET_SUBJECT,
TICKET_TAG
)
when:
response = controller.createTicket(
request,
authentication
)
then:
response != null
}
I'm getting the following error :
Suspend function 'create' should be called only from a coroutine or another suspend function.
Can anyone help me with this question ?
Best regards
Solved I created a Kotlin class code
class CallCreateTicket {
private lateinit var response: HttpResponse<Any>
private fun createTicket(
request: CreateTicketRequest,
authenticator: Authenticator,
controller: TicketController,
): HttpResponse<Any> {
runBlocking {
response = controller.createTicket(request, authenticator)
}
return response
}
}
and I called it on groovy ...
#Mockable(TicketCreateServiceImpl)
class TicketControllerTest extends Specification {
def mockUtil = new MockUtil()
def service = Mock(TicketCreateServiceImpl)
def authenticator = Mock(Authenticator)
def response = Mock(HttpResponse)
def controller = new TicketController(service)
def callCreateTicket = new CallCreateTicket()
def 'check if all instances are mocked'() {
mockUtil.isMock(authentication)
mockUtil.isMock(service)
}
def 'It should call the index function and return a valid String'() {
when:
response = controller.index()
then:
response == INDEX_RETURN
}
def 'It should call the index function and return a invalid String'() {
when:
response = controller.index()
then:
response != INVALID_INDEX_RETURN
}
def 'It should create a ticket with success'() {
given:
def request = createRequest(
TICKET_ID,
TICKET_NAME,
TICKET_PHONE,
TICKET_CPF,
TICKET_EMAIL,
TICKET_COMMENT,
TICKET_SUBJECT,
TICKET_TAG
)
when:
response = callCreateTicket.createTicket(
request,
authenticator,
controller
)
then:
response.status(HttpStatus.CREATED)
}
}

SQLite error "near "#gmail": syntax error "flutter

Here's the error I get:
E/SQLiteLog(25090): (1) near "#gmail": syntax error .
It seems like there is a problem in email input.
I guess there is nothing wrong in the creating of database.
creating db:
class UsersTable {
static const String tableName = 'Users';
static const String id = 'id';
static const String email = 'email';
static const String createQuery = '''
CREATE TABLE IF NOT EXISTS $tableName (
$id integer primary key autoincrement,
$email text not null unique);''';
}
in model class:
class Users {
late final int id;
late String email;
Users({
required this.id,
required this.email,
});
Users.fromDb(Map<String, dynamic> map) {
id = map[UsersTable.id];
email = map[UsersTable.email];
}
}
in UserService class which I think is where the problem arise:
class UserService {
...
Future<Users> getOrCreateUser({
required String email,
bool setAsCurrentUser = true,
}) async {
try {
//we found the user
final user = await getUser(email: email);
if (setAsCurrentUser) {
_user = user;
}
return user;
} on CouldNotFindUser {
//we didn't find the user
final createdUser = await createUser(email: email);
if (setAsCurrentUser) {
_user = createdUser;
}
return createdUser;
} catch (e) {
rethrow;
}
}
Future<Users> getUser({required String email}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final results = await db.query(
UsersTable.tableName,
limit: 1,
where: 'email = ?',
whereArgs: [email.toLowerCase()],
);
if (results.isEmpty) {
throw CouldNotFindUser();
} else {
return Users.fromDb(results.first);
}
}
...}
in main class:
...
Widget build(BuildContext context) {
return FutureBuilder(
future: _userService.getOrCreateUser(email: userEmail),
builder: (context, snapshot) {
return Provider(
create: (ctx) => HomePageController(),
dispose: (ctx, HomePageController controller) =>
...
how can I solve this error?

How to update nested structure of a published variable using another api call

I have a published var called spotWallet in my BinanceStore class which conforms to observaleObject. I can create a publisher and subscribe to it. but there is property in my top level struct called balances which is an array of Balance struct. What I want to achieve is would like to update a property of Balance called price which comes from another network call. I cannot get that to work, in clean combine swiftui way.
class BinanceStore: ObservableObject, Identifiable {
#Published var spotWallet: SpotWallet?
#Published var loadingError: String = ""
#Published var showAlert: Bool = false
private var cancellableSet: Set<AnyCancellable> = []
private let binanceFetcher: BinanceFetchable
init(binanceFetcher: BinanceFetchable) {
self.binanceFetcher = binanceFetcher
}
func AccountDetailsOnSpot() async {
binanceFetcher.getAccountDetailsOnSpot()
.sink { (dataResponse) in
if dataResponse.error != nil {
self.createAlert(with: dataResponse.error!)
} else {
self.spotWallet = dataResponse.value!
}
}.store(in: &cancellableSet)
}
func createAlert( with error: NetworkError ) {
loadingError = error.localizedDescription
self.showAlert = true
}
}
struct SpotWallet: Codable, Hashable {
let makerCommission, takerCommission, buyerCommission, sellerCommission: Int
let canTrade, canWithdraw, canDeposit: Bool
let updateTime: Int
let accountType: String
let balances: [Balance]
let permissions: [String]
}
protocol BinanceFetchable {
func getAccountDetailsOnSpot() -> AnyPublisher<DataResponse<SpotWallet, NetworkError>, Never>
}
class BinanceFetcher {
var coinPublisher = PassthroughSubject<CoinBalance, Never>()
}
extension BinanceFetcher: BinanceFetchable {
func getAccountDetailsOnSpot() -> AnyPublisher<DataResponse<SpotWallet, NetworkError>, Never> {
let endpoint = "/api/v3/account"
let params = BinanceWrapper.shared.makeRequestReady(queries: nil)
let url = URL(string: "\(BinanceWrapper.BINANCE_BASE_URL)\(endpoint)")!
return AF.request(url, parameters: params, encoding: URLEncoding.default, headers: BinanceWrapper.BINANCE_HTTP_HEADERS)
.validate()
.publishDecodable(type: SpotWallet.self)
.map { response in
response.mapError { error in
return NetworkError.parsing(description: error.localizedDescription)
}
}
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}

Flutter: how to mock a stream

I´m using the bloc pattern and now I came to test the UI. My question is: how to mock streams?
This is the code that I have:
I give to the RootPage class an optional mockBloc value and I will set it to the actual _bloc if this mockBloc is not null
class RootPage extends StatefulWidget {
final loggedOut;
final mockBlock;
RootPage(this.loggedOut, {this.mockBlock});
#override
_RootPageState createState() => _RootPageState();
}
class _RootPageState extends State<RootPage> {
LoginBloc _bloc;
#override
void initState() {
super.initState();
if (widget.mockBlock != null)
_bloc = widget.mockBlock;
else
_bloc = new LoginBloc();
if (widget.loggedOut == false)
_bloc.startLoad.add(null);
}
...
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _bloc.load,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: <Widget>
...
This is what I´ve tried:
testWidgets('MyWidget', (WidgetTester tester) async {
MockBloc mockBloc = new MockBloc();
MockTokenApi mockTokenApi = new MockTokenApi();
await tester.pumpWidget(new MaterialApp(
home: RootPage(false, mockBlock: mockBloc)));
when(mockBloc.startLoad.add(null)).thenReturn(mockBloc.insertLoadStatus.add(SettingsStatus.set)); //this will give in output the stream that the StreamBuilder is listening to (_bloc.load)
});
await tester.pump();
expect(find.text("Root"), findsOneWidget);
});
The result that I achieve is always to get:
The method 'add' was called on null
when _bloc.startLoad.add(null) is called
You can create a mock Stream by creating a mock class using mockito. Here's a sample on how one can be implemented.
import 'package:mockito/mockito.dart';
class MockStream extends Mock implements Stream<int> {}
void main() async {
var stream = MockStream();
when(stream.first).thenAnswer((_) => Future.value(7));
print(await stream.first);
when(stream.listen(any)).thenAnswer((Invocation invocation) {
var callback = invocation.positionalArguments.single;
callback(1);
callback(2);
callback(3);
});
stream.listen((e) async => print(await e));
}
Since the advent of null safety, you can do this as follows:
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'test_test.mocks.dart';
#GenerateMocks([Stream])
void main() {
test('foo', () async {
var stream = MockStream();
Stream<int> streamFunc() async* {
yield 1;
yield 2;
yield 3;
}
when(stream.listen(
any,
onError: anyNamed('onError'),
onDone: anyNamed('onDone'),
cancelOnError: anyNamed('cancelOnError'),
)).thenAnswer((inv) {
var onData = inv.positionalArguments.single;
var onError = inv.namedArguments[#onError];
var onDone = inv.namedArguments[#onDone];
var cancelOnError = inv.namedArguments[#cancelOnError];
return streamFunc().listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
});
stream.listen((e) async => print(await e));
});
}
source

How to save GORM class with composite id made from its own field?

This is my Domain class
class ReturnReason implements Serializable {
Long returnReasonId
Long languageId
String name
int hashCode() {
def builder = new HashCodeBuilder()
builder.append returnReasonId
builder.append languageId
builder.toHashCode()
}
boolean equals(other) {
if (other == null) return false
def builder = new EqualsBuilder()
builder.append returnReasonId, other.returnReasonId
builder.append languageId, other.languageId
builder.isEquals()
}
static mapping = {
id composite: ["returnReasonId", "languageId"]
version false
}
static constraints = {
name maxSize: 128
}
}
This is my controller code to save my domain class.
def save() {
ReturnReason returnReasonInstance = new ReturnReason(params)
returnReasonInstance.languageId = 1
if (!returnReasonInstance.save(flush: true)) {
render(view: "create", model: [returnReasonInstance: returnReasonInstance])
}
redirect(action: "list")
}
While trying to save in my controller than there is a error in returnReasonId ,i.e returnReasonId rejected value null. How to fix it.??
write validate:false in save action
def save() {
ReturnStatus returnStatusInstance = new ReturnStatus(params)
returnStatusInstance.languageId = 1
if (!returnStatusInstance.save(validate: false, flush: true)) {
render(view: "create", model: [returnStatusInstance: returnStatusInstance])
}
redirect(action: "list")
}