Custom login page episerver - episerver

So I am trying to create a custom login page instead of the EPi Server. Right now I have created a custom controller and model and page using this tutoiral
https://world.episerver.com/blogs/Daniel-Ovaska/Dates/2016/6/creating-a-custom-login-page/
The thing is when I type http://localhost:53067/LoginPage/Index in the browser window I get null for the currenPage in the below code
public ActionResult Index(LoginPage currentPage, [FromUri]string ReturnUrl)
{
/* Implementation of action. You can create your own view model class that you pass to the view or
* you can pass the page type for simpler templates */
var model = new LoginModel(currentPage);
model.LoginPostbackData.ReturnUrl = ReturnUrl;
return View(model);
}
Does anyone know what am I missing here?

The currentPage parameter will only have a value if there is a page of type LoginPage which maps to the URL.
It seems you're simply browsing to the controller route.
If you create a page of type LoginPage called "My login page", it should get a URL like http://localhost:53067/my-login-page.
If you then browse to that URL, your Index method will be invoked, assuming your controller inherits PageController.

Related

Terminate user session when the browser or tab closes

I want to ultimately have user sessions end once the browser or tab is closed, and so far i had no luck. I have tried to enable offline_access in the IdentityServer config and in the client config but that doesn't seem to help. I am seeking some help with having my setup function in this way.
I use the flow of SignIn that redirects you too the IS4 login page then upon successful login you get redirected to the client app.
Here's how I handle it: I'm using a JavaScript sessionStorage variable to sense when the user has closed the browser (or tab).
<script>
var readValue = sessionStorage['checksession'];
</script>
If the browser was closed the variable will be undefined. In that case, I call a server-side page method to redirect the user to the login form:
<script>
var readValue = sessionStorage['checksession'];
if (readValue == null) {
// Redirect to Login
PageMethods.BrowserClosed();
}
</script>
Server side page method must be static and marked as [WebMethod]:
[WebMethod]
public static void BrowserClosed()
{
Util.hasClosedBrowser = true;
}
The static web method updates a boolean property in a static utility class (Util.cs) that I use in my asp.net project.
In Util.cs:
public static bool hasClosedBrowser { get; set; }
In the asp.net Page.Load event, I am looking for a "true" value in the "hasClosed" property defined in the utility class. If it's true, I call the Logout() method, which redirects to the login form:
if (Util.hasClosedBrowser)
{
Logout();
return;
}
At the end of the .aspx page after all of the elements, in a script tag I am setting the sessionStorage variable:
sessionStorage['checksession'] = "somevalue";
You can use any value in the sessionStorage cookie that you want, just know that it has to be a string unless you want to format it as a JSON string.
What's great about this approach is it correctly redirects to the Login form when the browser or the tab page was closed, but does not fire when the user simply refreshes the page (assuming the session hasn't actually expired). On a refresh, and as long as the session has not expired, the user's login state remains intact because the variable will still be present in sessionStorage.
Cheers,
-=Cameron

Post data from angularjs to MVC action method which returns a view

I have a button in my view and on clicking the button i want to redirect to mvc action method with an object. The action method will then return another view which will then be displayed to the user.
This is the button
<button id="btnPreview" type="button" class="btn" ng-click="RedirectToBuyFlow(PreviewOfferId)" ng-model="PreviewOfferId">Preview Offer</button>
This is the function which is called on ng-click of the above button.
$scope.RedirectToBuyFlow = function (PreviewOfferId) {
if (PreviewOfferId != null && PreviewOfferId != undefined && PreviewOfferId != "") {
$http.post("/App/MockBuyflow/Qualify", PreviewOfferId);
}
}
The controller name is MockBuyflow and the action method is as below
[HttpPost]
public virtual ActionResult Qualify(string OfferId)
{
//do something
return(view);
}
The problem is that it never hits my action method. However if instead of $http.post i use
window.location.href="/App/MockBuyflow/Qualify?OfferId=3036"
it works fine. But since i have to do a post request i cannot use window.location.href. What am i doing wrong in post?
Please help.
When you just add the number to the $http method, it will just put it in the Http body for the request.
And ASP.NET MVC, won't know what to map it with, and will skip it.
Do this instead:
$http.post("/App/MockBuyflow/Qualify", {OfferId: PreviewOfferId});
By writing {OfferId: PreviewOfferId}
You are sending a JSON object to the server, and ASP.NET will know that you want to map that value into your OfferId input on the action.
I also believe that in later versions of ASP.NET MVC, you can use the [FromBody] attribute, to specify that the value can be found in the body of the request as follows:
Javascript:
$http.post("/App/MockBuyflow/Qualify", PreviewOfferId);
C#:
[HttpPost]
public virtual ActionResult Qualify([FromBody]string OfferId)
{
//do something
return(view);
}

Cakephp 3 - CRUD plugin - Use id from auth component

Currently, I'm using the CRUD v4 plugin for Cakephp 3. For the edit function in my user controller it is important that only a user itself can alter his or her credentials. I want to make this possible by inserting the user id from the authentication component. The following controller method:
public function edit($id = null){
$this->Crud->on('beforeSave', function(\Cake\Event\Event $event) {
$event->subject()->entity->id = $this->Auth->user('id');
});
return $this->Crud->execute();
}
How can I make sure I don't need to give the id through the url? The standard implementation requires the url give like this: http://domain.com/api/users/edit/1.json through PUT request. What I want to do is that a user can just fill in http://domain.com/api/users/edit.json and send a JSON body with it.
I already tried several things under which:
$id = null when the parameter is given, like in the example above. Without giving any id in the url this will throw a 404 error which is caused by the _notFound method in the FindMethodTrait.php
Use beforeFind instead of beforeSave. This doesn't work either since this isn't the appropriate method for the edit function.
Give just a random id which doesn't exist in the database. This will through a 404 error. I think this is the most significant sign (combined with point 1) that there is something wrong. Since I try to overwrite this value, the CRUD plugin doesn't allow me to do that in a way that my inserting value is just totally ignored (overwriting the $event->subject()->entity->id).
Try to access the method with PUT through http://domain.com/api/users.json. This will try to route the action to the index method.
Just a few checks: the controllerTrait is used in my AppController and the crud edit function is not disabled.
Does anyone know what I'm doing wrong here? Is this a bug?
I personally would use the controller authorize in the Auth component to prevent anyone from updating someone else's information. That way you do not have to change up the crud code. Something like this...
Add this line to config of the Auth component (which is probably in your AppController):
'authorize' => ['Controller']
Then, inside the app controller create a function called isAuthorized:
public function isAuthorized($user) {
return true;
}
Then, inside your UsersController you can override the isAuthorized function:
public function isAuthorized($user) {
// The owner of an article can edit and delete it
if (in_array($this->request->action, ['edit'])) {
$userId = (int)$this->request->params['pass'][0];
if ($user['id'] !== $userId) {
return false;
}
}
return parent::isAuthorized($user);
}

Restrict External Access to Controller, but enable access from Model (CakePHP 2.X)

In our application we are using the Controller and View to generate a PDF file which can be emailed to a user, the Controller renders a view file and passes it back to the model.
It has been setup like this because in another part of the application we use the same view file to display the PDF on-page (which requires POST data).
My problem is that I need to be able to access the controller functions from my model, however I want to prevent someone (using the website directly) from executing the controller function directly.
In Model:
$Contents = new ContentsController();
$message = $Contents->generatePDF($viewVars);
In Controller:
public function generatePDF($input_data)
{
//set the original data and the check result to build the page:
foreach($input_data as $key => $value)
{
$this->set($key, $value);
}
//instantiate a new View class from the controller
$view = new View($this);
$viewData = $view->render('pdf_file', 'pdf');
return $viewData;
}
Which works, however if the user goes and types /Contents/generatePDF into their browser they can access this controller function, so I want to be able to prevent it being accessed from the web directly.
I am using CakePHP 2.X
The simplest approach is to prepend an underscore to the name of your controller method: _generatePDF. Such methods are not accessible via browser.

CakePHP default layout, can't pass values to default.ctp

I have one page website, on homepage(Layout/default.ctp) I have 2 forms, subscribe and contact form that are being controlled over contact controller. With $this->set('some_val', 'test'); I can set value from AppController, but not from contact controller, how can I set values from contact controller to be available in default.ctp except with sessions?
public function beforeFilter() {
parent::beforeFilter();
//pr('beforeFilter'); // i was testing is this happening or not
//exit();
$tester = 'test';
$this->set(compact('tester'));
}
and in default.ctp I just pr($this->viewVars); to make sure that I have tester value, but it is always empty.
Is this right approach how to implement several controllers in one page design?
Another question is there a place/function where I could check is current request post or not, I would like to check for each request what is it?
Thank you.
Not sure if I understand correctly, but it sounds like you might need multiple layouts:
class CarsController extends AppController
{
public function index($page)
{
/* Your logic */
if ( $page == 'other' ) {
$this->render('view', 'layout');
} else {
$this->render('view-other', 'layout-other');
}
}
}
For more information i'd suggest looking at: http://api20.cakephp.org/class/controller#method-Controllerrender
try an echo $tester; in your default, it should be available.
If the request is post, you would have data in $this->data.

Resources