Ionic 2 app: remember user on the device - authentication

I have an Ionic App and I'd like to put a "Remember me" checkbox in the login page, so that once the user has logged in he'll be logged in forever (unless he logouts), even if he close and re-opens the application, just as the Facebook app does.
Is there a way to do that in Ionic 2?
Thanks!

You can use localstorage to save some data for your own verification/logic handling.It's html5 supported and easy to use. The downside would be it won't be secure and it might be erased by system when there's low memory or clearing of cache.
HTML(Upon button press, but u can set it to your own preference):
<button secondary (click)="addLocalStorage()">Done</button>
In your controller:
import {Storage, LocalStorage} from 'ionic-angular';
constructor(navController, local) {
this.navController = navController;
this.local = new Storage(LocalStorage);
}
addLocalStorage(){
this.local.set("didTutorial","true");
//set the doneTutorial to be true
}
Explanation:
At the constructor , we create an new localstorage object called 'local'.
To call it, we use 'this.local' and 'set' is the method to store it.
Set(Key,Value)
In the example code above, i use 'didTutorial' as the key and 'true' as the value.
To retrieve it, you can retrieve it at this page or at any other page.
Just remember to import Storage and LocalStorage and declare a new localstorage object in the constructor.(same as above)
The code to retrieve is :
var value = localStorage.getItem('didTutorial');
getitem(Key,Value)

You can use storage and sqlStorage to save user data. And then check it for saved user.
Refer :-
https://www.thepolyglotdeveloper.com/2015/12/use-sqlite-in-ionic-2-instead-of-local-storage/
Hope this helps!

localStorage works fine but I confirm the drawbacks that #Gene talks about. It is not reliable, especially on iPhones that do not have much free storage
I use ionic 1 so I cannot try this solution, but you might want to check this out : https://ionicframework.com/docs/native/native-storage/
; could be more reliable!

Related

Store an array on the app group for WidgetKit

I'm trying to store an struct array into the app group container to use it later on the widget.
let's assume, I have an array of string
let = array = ["object1", "object2", "object3"]
and I saw here I can access to the app group container url
let applicationGroupId = "group.com.development.widget"
guard let groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupId) else {
fatalError("could not get shared app group directory.")
}
Now, I need to know how I can store this array on app group and how I can read from it on the Widgetkit SwiftUI class
Your help will be appreciated.
Signing, Capabilities, Entitlements
Right now it should be possible to do all of this from within Xcode (12+). In the app's project settings go to the Signing & Capabilities tab and make sure Automatically manage signing is enabled and the Team has a valid development team (either company or personal account).
Tap on the + Capability button on the top left to enter the App Group Capability (this will also add an entitlements file). Now you will find an App Group section. Hit the + button for App Groups and enter a globally unique identifier (something like group.<appid>). This will create the app group on the developer platform and add it to your app's provisioning profile and entitlements.
You must repeat the same steps and use the same app group for all targets (app target, widget extension target and (optionally) intent targets). If you hit the reload button for the other targets' app group it should automatically show the app group you previously registered and you can check the checkbox. If not, hitting + and using the same id should work as well.
Finally, check all entitlements files and ensure that they have the same String in App Groups (copy and paste just to make sure).
Code
In code you now just have to access the user defaults using the chosen app group as suitName. To test whether everything is set up correctly, I would put the following line in application(_:didFinishLaunchingWithOptions):
UserDefaults(suiteName: "group.id.test")!.setValue(["object1", "object2", "object3"], forKey: "test")
In the Widget just try to put it in a Text view:
struct WidgetTestEntryView : View {
var entry: Provider.Entry
var text: String {
(UserDefaults(suiteName: "group.id.test")!.value(forKey: "test") as? [String])?.joined(separator: " ") ?? "Nothing stored yet"
}
var body: some View {
Text(text)
}
}
Note: I force unwrap the user defaults on purpose to fail early and check whether the setup of capabilities/signing worked. In production you should guard against a failure.
Alternative Storage
As you pointed out it's also possible to persist data in a shared container by writing to url provided by FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:) but I don't think you need that for your simple example. If you want to share data that is more complex than String, Int, Array ... make sure to convert it to Data since user defaults cannot handle arbitrary data (even if it's Codable).
Manual Signing
If you use manual signing you just have to do the same step in the developer console starting with registering an app group. After that, add the group to all identifiers' capabilities and recreate all provisioning profiles. From there you should be use similar steps to the ones described above.

Porting Yii1's $user->setState('key', 'value') to Yii2

I'm upgrading a Yii1 app to Yii2 and got stuck at porting
Yii::app()->user->setState('key', 'value');
Yii::app()->user->getState('key');
to
Yii::$app->user->XXXX('key', 'value');
Yii::$app->user->XXXX('key');
I know the setState method sets a value in the session (And db if the session is also in the db), but I can't figure out which of the new \yii\web\User method I should use as none of the login, setIdentity, switchIdenty methods seem to work the same way.
More info if needed: The "setState()" code is used to save the user id entered in a text field, which will then be used on the next page to ask the password.
This feature was dropped in Yii2. You should use Yii::$app->session in this cases, because setState/getState was just simple wrappers on it.
About prefix for user session
Simply use
Yii::$app->session->set('user.some_param',$someparam);
and use below to retrieve
Yii::$app->session->get('user.some_param' , $defaultValue);
Or you can implement this feature from Yii1 in your own class. For flashes see CODE

Auth0 and Vue: Error in render function: "InvalidTokenError: Invalid token specified: Cannot read property 'replace' of undefined"

guys, I'm going through the VueJS tutorial for Auth0, and am getting this error:
InvalidTokenError {message: "Invalid token specified: Cannot read property 'replace' of undefined"}
message:"Invalid token specified: Cannot read property 'replace' of undefined"
The tutorial is here:
https://auth0.com/blog/vuejs2-authentication-tutorial/
The error is happening right when the app is supposed to bring up the Auth0 Lock widget.
Thoughts?
Clear your browser's local storage cache.
e.g
for Chrome, press F12 to go to developer window, Storage\Local Storage, right click and clear.
For IE, F12 to developer window. On 'Console' tab, run the command
localStorage.clear()
Sorry I cannot comment on your question because my rank is too low. I had the same error coming up when I followed the react version of you tutorial.
The issue in my case was due to the fact that in the auth.js file, there is a function called getTokenExpirationDate(encodedToken). Inside that function the line const token = decode(encodedToken); was the cause of the bug.
By investigating the value of encodedToken I found out that it's value was a string with the characters 'none', (not the value none itself!). This makes the encode function very unhappy.
If you go in the chrome developer tools, click on the Application tab, open the Local Storage option on the left hand side and select you site. You will be able to see all the key-value pairs stored in your local storage for your app. In my case the key id_token had the value none. If it's the case for you too, just delete that key/value pair from the local storage and the page should be able to load again.
Hope this helped and good luck!
Edit
By playing with local storage with chrome developer tools I realised the local storage can be a bit buggy. Sometimes I try to view the local storage but it doesn't appear. When that happens just try closing and reopening the tool.
I also was running into this issue. I had one rule called 'auth0-authorization-extension' activated that triggered this error.
This fixed it for me. It is in typescript. You can remove (token: string) to (token) if not using TS
function parseJwt (token: string) {
var base64Url = token.split('.')[0];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
};
if you have token in another place, you can copy token in cookies.
you can find your token in Insomia software.
you can copy it
come back to browser and open inspect with F12
open cockies and paste token there

User Specific App Settings

I have started working with server side app settings and it would appear the default mechanics for a shared app is to save the app settings across the entire project scope; so if an individual makes changes to the app settings, those changes are reflected for all future users. This is not the ideal use in my specific case. I would like it if I could have different settings for each user, without them each adding separate instances of my custom HTML. Is this possible using server side settings, or will I need to look into using cookies to save the settings on each user?
Note: I've read the documentation on app setting scope (https://help.rallydev.com/apps/2.0rc1/doc/#!/guide/settings-section-define-scope) but it doesn't appear as though "user" is an option.
Thanks!
Conner, you're making a good argument for User-level settings for an app.
Unfortunately, we don't support that currently. The settingsScope option in AppSettings only supports the values app, project, or workspace.
Creating an instance of the app for each user (such as on their individual dashboard) is the best alternative I can think of. But as you mentioned, this is not ideal for you.
I have solved this issue by prepending the user ObjectID to each setting value before I save or load it from the Rally servers. Here is the code for my user settings set/get functions:
setUserSetting : function(settingName, settingValue, callback) {
var settings = {};
settings[App.getContext().getUser().ObjectID + settingName] = settingValue;
App.updateSettingsValues({
settings : settings,
success : function() {
App.setSettings(Ext.Object.merge(App.getSettings(), settings));
callback();
}
});
},
getUserSetting : function(settingName) {
return App.getSetting(App.getContext().getUser().ObjectID + settingName);
}
BTW, it seems kind of strange that I have to save the settings in the way I have. The "updateSettingsValues" function sets the settings on the next load of the app and the "setSettings" function sets it for the current runtime of the app. It's a strange way to have to do it, but it works.

Kaltura - Force player to stop with API only?

Is there any way to force a Kaltura videoplayer to stop ONLY using code and the Kaltura API?
Currently I have solved it by adding a Access Control Profile named "Free preview" under Settings > Access Control in KMC and then added this profile to the Entries I've choosen.
I then add the session to the players flashvars to restrict non-members to only watch the preview, not the whole clip.
But I would like to restrict ALL, or even better selected Categories of clips by using only code, so I don't need to involve KMC.
Is that possible?
Alt) Can you create a new player in KMC and restrict it to viewing only X seconds, no matter what length of Entry? Then I can do the check if user is valid or not and get the category via API and show it in the "preview-player" och the "default player".
If I use the mediaProxy.mediaPlayTo attribute the clip stops, but is easily started again by presing play.
Would greatly appreciate an answer
I got this answer from a guy named oferc in a different forum:
You can listen to the head move event and pause the clip it goes beyond a certain time (then if someone pressed play, you can stop it again)
function jsCallbackReady(player_id) {
my_kdp = $("#"+player_id).get(0); // document.getElementById(player_id) if you do not use jquery/ prefer pure js
my_kdp.addJsListener("kdpReady", "kdpReady"); // when you load the player with an entry (and the player is ready to begin playing it using doPlay for instance)
}
function kdpReady() {
my_kdp.addJsListener("playerUpdatePlayhead","headMove");
}
function headMove(position) {
if (position > "30") { // Your Time, example 30 seconds
my_kdp.sendNotification('doStop')
}
}
Works like a charm!
fredrik_w - neither of the ways you chosen here are a good option to restrict access.
in both cases, your videos are made public, and can be easily accessible by anyone.
The best way to limit access to a video is by defining an Access Control, and like everything in Kaltura, you can define an ACL using API as well.
Check this out as a reference sample-
http://blog.kaltura.org/turning-profit-online-video-made-easy-using-paypal-html5-digital-goods