MVC partially restrict view access to users that are not admins - javascript

Is it possible to restrict access to certain parts of a view based on a Access Restriction? Currently I can limit users from getting to pages by doing this in the controller
[RestrictAccess(restriction = AccessRestrictions.Admin)]
But is it possible for me restrict a certain aspect from the page while still allowing other users access to the page?
Here is model that checks if user has access
public enum AccessRestrictions
{
[Display(Name = "Admin")]
Admin
}
public class userAccess
{
[Key]
public int ID { get; set; }
public AccessRestrictions restriction { get; set; }
public bool allow { get; set; }
public int userID { get; set; }
}
public class configDetails
{
public int ID {get; set;}
public string Name {get; set;}
public string Value {get;set;}
public bool deleted {get;set;}
public DateTime updateTime { get; set; }
}
public class Config
{
public int ID { get; set; }
[Display(Name = "Configuration Date")]
public DateTime TargetDate { get; set; }
[Display(Name = "Enable Access Restrictions")]
public bool restrictAccess { get; set; }
}

Let's say you have follow view
<div id="CallList">
#Html.Action("List","Call",new {id=Model.id})
</div>
<div class="Order">
#Html.Action("Create","Order",new {id=Model.id})
</div>
With follow actions:
[Authorize(Roles = "manager, caller")] //if a user is not 'manager' or 'caller'
public PartialViewResult List() // nothing is shown
{
//...private
return PartialView();
}
[Authorize(Roles = "manager, admin")]
public PartialViewResult Create()
{
//...private
return PartialView();
}
Then you can limit access via this ext. method
public static MvcHtmlString ActionBaseRole(this HtmlHelper value, string actionName, string controllerName, object routeValues , IPrincipal user)
{
bool userHasRequeredRole = false;
Type t = Type.GetType((string.Format("MyProject.Controllers.{0}Controller",controllerName))); // MyProject.Controllers... replace on you namespace
MethodInfo method = t.GetMethod(actionName);
var attr = (method.GetCustomAttribute(typeof(AuthorizeAttribute), true) as AuthorizeAttribute);
if (attr != null)
{
string[] methodRequeredRoles = attr.Roles.Split(',');
userHasRequeredRole = methodRequeredRoles.Any(r => user.IsInRole(r.Trim())); // user roles check in depends on implementation authorization in you site
// In a simple version that might look like
}
else userHasRequeredRole = true; //method don't have Authorize Attribute
return userHasRequeredRole ? value.Action(actionName, controllerName, routeValues) : MvcHtmlString.Empty;
}
Example of usage:
#Html.ActionBaseRole("List","Call",new {id=Model.id},User)
Note your security attributes are different but I think you can easy replace it.

Related

p:commandButton execution order of events

I am using PrimeFaces 6.0 components:
<p:commandButton type="submit" value="Create Customer"
icon="ui-icon-check"
actionListener="#{newCustomerBean.saveNewCustomer}"
update = "#form"
oncomplete="ajaxUploadFile();"/>
<p:inputText id="saveCustomerId" value ="#{newCustomerBean.savedKundeId}"/>
and I want to execute the following sequence of actions with them:
1.) Execute the actionListener method on the backing bean to save a customer;
2.) Update the form field saveCustomerId with the id of the customer that is saved on step (1). The actionListener method generates a customer Id after the successful save and stores is as a bean property;
3.) Execute the Java Script method ajaxUploadFile()
According to the link
Execution order of events when pressing PrimeFaces p:commandButton
this sequence shall be as I have imagined.
However, in reality, the method
ajaxUploadFile()
is called BEFORE the input field with id saveCustomerId is updated.
Could you help me get the right sequence?
Here is the backing bean:
#ManagedBean
#ViewScoped
public class NewCustomerBean implements Serializable {
public enum KundeTyp {
TYP_NATPERS("Nat. Person"), TYP_FIRMA("Firma");
private String value;
private KundeTyp(String value) {
this.value = value;
}
#Override
public String toString() {
return value;
}
}
private KundeTyp custmerType;
private Map<String, KundeTyp> custmerTypes;
private long savedKundeId;
#Inject
private KundeDBService kundeService;
private String vorname;
private String addresse;
private String steuerNummer;
private String kundeTyp = Integer.MIN_VALUE + "";
#PostConstruct
public void init() {
custmerTypes = new HashMap<String, KundeTyp>();
custmerTypes.put(KundeTyp.TYP_NATPERS.value, KundeTyp.TYP_NATPERS);
custmerTypes.put(KundeTyp.TYP_FIRMA.value, KundeTyp.TYP_FIRMA);
}
public KundeTyp getCustmerType() {
return custmerType;
}
public void setCustmerType(KundeTyp custmerType) {
this.custmerType = custmerType;
}
public Map<String, KundeTyp> getCustmerTypes() {
return custmerTypes;
}
public void setCustmerTypes(Map<String, KundeTyp> custmerTypes) {
this.custmerTypes = custmerTypes;
}
public String getVorname() {
return vorname;
}
public void setVorname(String vorname) {
this.vorname = vorname;
}
public String getAddresse() {
return addresse;
}
public void setAddresse(String addresse) {
this.addresse = addresse;
}
public String getSteuerNummer() {
return steuerNummer;
}
public void setSteuerNummer(String steuerNummer) {
this.steuerNummer = steuerNummer;
}
public String getKundeTyp() {
return kundeTyp;
}
public void setKundeTyp(String kundenTyp) {
this.kundeTyp = kundenTyp;
}
public String saveNewCustomer(ActionEvent e) {
Kunde neuerKunde = null;
switch (this.custmerType) {
case TYP_NATPERS: {
neuerKunde = new NatuerlichePerson();
break;
}
case TYP_FIRMA: {
neuerKunde = new Firma();
((Firma) neuerKunde).setSteuerNummer("123456");
break;
}
}
neuerKunde.setVorname(vorname);
neuerKunde.setAdresse(this.addresse);
try {
savedKundeId = kundeService.saveKunde(neuerKunde);
} catch (ServiceException se) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error",
"Unable to save the new customer: " + se.getMessage()));
}
return null;
}
public long getSavedKundeId() {
return savedKundeId;
}
public void setSavedKundeId(long savedKundeId) {
this.savedKundeId = savedKundeId;
}
}
I would propose a work-around here, since I was not able to find a solution.
Instead of updating the customerId on the front-end, we put it as a session attribute in the HttpSession.
Then, in the UploadServlet, which handles the file upload, we read this attribute and save the image under this customerId.

Getting Value from DropDownList to partial view using Ajax

I'm a novice in javascript, and a junior developper in OOP.
After many attempts and many google search I dind't make it to solve it.
I have a DropDownList and a Partial View. I want to give the selected value to the partial view controller. It works when I write the value directly in, but it doesn't if i try to catch the DropDownList value. For the moment the value returned is always empty.
Model
public partial class Clients
{
public int ClientID { get; set; }
public string Code { get; set; }
public string Nom { get; set; }
public string Adresse1 { get; set; }
public string Adresse2 { get; set; }
public string CP { get; set; }
public string Ville { get; set; }
public Nullable<System.DateTime> DateCreation { get; set; }
public Nullable<System.DateTime> DateModification { get; set; }
}
View
#Html.DropDownList("id", (IEnumerable<SelectListItem>)ViewData["oas"], new { #id = "ClientID" })
<div id="result"></div>
<script>
$(function () {
$('#ClientID').change(function () {
//var pid = $("#id").val();//$(this).data('id');
$('#result').load('#Url.Action("filter")',
{ id: $("#id").val() } //replacing $("#id").val() by "3" makes it work, but i of course don't a constant value here
);
});
});
Controller
public class OnePageController : Controller
{
Entities db = new Entities();
public ActionResult Index()
{
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem { Text = "-Please select-", Value = "Selects items" });
var clts = (
from c in db.Clients
select c).ToArray();
for (int i = 0; i < clts.Length; i++)
{
list.Add(new SelectListItem
{
Text = clts[i].Nom,
Value = clts[i].ClientID.ToString(),
Selected = (clts[i].ClientID == 1)
});
}
ViewData["oas"] = list;
return View(/*db.Clients.ToList()*/);
}
[HttpPost]
public ActionResult Filter(string id)
{
var contact = from c in db.Contacts
where c.ClientID.ToString() == id
select c;
return PartialView(contact);
}
}
Any idea would be greatly appreciated, also i don't know how to debug javasript, i use the developper tools in my when browser to try to catch the values, but i don't really track the changes..
You should change a bit your script:
$(function () {
// You select the element with id = ClientID
var clientEle = $('#ClientID');
// You register an event handler for the change of the selected value
clientEle.change(function () {
// clientEle.val() would return the selected value
$('#result').load('#Url.Action("filter")',{ id: clientEle.val() });
});
});
Regarding how you should debug JavaScript I would suggest to write the following keyword a few lines before you want to start the debugging:
debugger;
Then open developer tools and refresh your page. When JavaScript engine hits the debugger would stop it's execution and from this moment you could examine you code line by line.
For a thorough understanding in how you could debug JavaScript, you could start by checking the following links
https://developers.google.com/web/tools/chrome-devtools/javascript/
https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript
https://www.w3schools.com/js/js_debugging.asp

Knockout failing to post a form, can't figure out why

I am developing a page with ASP.NET MVC and API, using Knockout, Typescript, and the code is as: JSFiddler
The server code:
// POST: api/Empresas
[ResponseType(typeof(Business))]
public async Task<IHttpActionResult> PostBusiness(Business business)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Businesses.Add(business);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = business.Id }, business);
}
Business Obj:
public class Business
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[ScaffoldColumn(false)]
public Guid Id { get; set; }
[Display(Name = "CNPJ", Description = "Cadastro Nacional de Pessoa Juridica")]
public string CNPJ { get; set; }
[Display(Name = "Nome", Description = "Razão Social")]
public string Name { get; set; }
[Display(Name = "Limite Mensal", Description = "Limite mensal de uso")]
public int MonthlyLimit { get; set; }
[Display(Name = "Mensal Atual", Description = "Uso Mensal Atual")]
public int MonthlyCurrent { get; set; }
[Display(Name = "Inicio Assinatura", Description = "Data inicial da assinatura")]
public DateTime SubscriptionStart { get; set; }
[Display(Name = "Meses Contratados", Description = "Numero de meses contratados")]
public int MonthContractCount { get; set; }
}
The example is not gonna work since there is not an end point to test against.
My first question is why won't the data-bind work for this?
Second and most important, I keep getting the following error message:
Message from webpage
[object Object]
parsererror
SyntaxError: Invalid character - failed to create business
OK
I have no idea why this is happening, and I have done multiple changes to the code with success. Any ideas?
Values I was using:
CNPJ = 123.321.321-25
Name = Test Business
monthlyLimit = 20000
SubscriptionStart = 01/01/2014
monthContractCount = 24
Thanks in advance
EDIT:
createBusiness = (formElement) => {}
I changed the signature on the method to look like the above, with attempt to solve the scope problem with "this" key word. Still not working though.
NEW EDIT:
createBusiness = (formElement) => {
$(formElement).validate();
if ($(formElement).valid()) {
var formserialized = $(formElement).serialize();
$.post('/Api/Empresas/', formserialized, null, "json")
.done((result) => {
this.Business.Id = result.Id;
this.Business.Name(result.Name);
this.Business.CNPJ(result.CNPJ);
this.Business.MonthlyLimit(result.MonthlyLimit);
this.Business.SubscriptionStart(result.SubscriptionStart);
this.Business.MonthContractCount(result.MonthContractCount);
this.Business.MonthlyCurrent(result.MonthlyCurrent);
})
.fail((x, y, z) => {
alert(x + '\n' + y + '\n' + z + ' - failed to create business');
});
};
}
This is the last change, and it worked now, but as you can see I had to change the this.BaseUri to '/Api/Empresas/' this change was necessary due to scope of "this", so this is a fix but not really. Any ideas there?
change
var formserialized = $(formElement).serialize();
to
var formserialized = JSON.stringify($(formElement).serialize());

Breeze newValue.getProperty is not a function

I've updated to new version of breeze and ef 6. And after I did this, I get error
newValue.getProperty is not a function
Whenever I try to execute expand query. (for "normal" queries everything is fine )
So here is my model for Mucsle:
public int MuscleId { get; set; }
public string Name { get; set; }
public int MuscleGroupId { get; set; }
public MuscleGroup MuscleGroup { get; set; }
And for MuscleGroup:
public int MuscleGroupId { get; set; }
public string Name { get; set; }
public ICollection<Muscle> Muscles { get; set; }
Here is my DtabaseContext Configuration:
public WebDatabaseContext()
: base("DefaultConnection")
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
}
And I try to fetch data like this:
Function in dataService:
getAllIncluding: function(controllerAction, including) {
var query = breeze.EntityQuery.from(controllerAction).expand(including);
return manager.executeQuery(query).then(querySucceeded).fail(getFailed);
function querySucceeded(data) {
items = data.results;
return data.results;
}
}
Call of function:
$scope.getAllMuscles = function() {
adminCrudService.getAllIncluding("Muscles", "MuscleGroup")
.then(querySucceeded)
.fail(queryFailed);
};
With older version of breeze and EF5 this works, so I wonder what am I doing wrong ?
EDIT
I believe, I've found what causes problem, when I enter in url:
breeze/Service/Muscles?$expand=MuscleGroup
With "old" (older version of breeze, and EF 5) settings, output is this:
[{"$id":"1","$type":"Test.Domain.Model.MuscleGroupAggregate.Muscle, Test.Domain.Model","MuscleId":1,"Name":"Biceps","NameInLatin":"","ImageUrl":null,"MuscleGroupId":1,"MuscleGroup":null},
{"$id":"2","$type":"Test.Domain.Model.MuscleGroupAggregate.Muscle, Test.Domain.Model","MuscleId":3,"Name":"Triceps","NameInLatin":"","ImageUrl":null,"MuscleGroupId":1,"MuscleGroup":null},
And with EF 6 and latest version of breeze:
[{"$id":"1","$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib","MuscleGroup":
{"$id":"2","$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib","MuscleGroupId":1,"Name":"TestMuscleG1","Description":"","ImageUrl":null},"MuscleId":1,"Name":"Test2","NameInLatin":"","ImageUrl":null,"MuscleGroupId":1},
{"$id":"3","$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib","MuscleGroup":
{"$id":"4","$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib","MuscleGroupId":1,"Name":"TestMuscleG1","Description":"","ImageUrl":null},"MuscleId":2,"Name":"32r23r","NameInLatin":"","ImageUrl":null,"MuscleGroupId":1}]
So difference is in $type, and in "new" output, even tough, in database I have only two entries, I got 4 items.
Solved it !
So the problem was here:
[HttpGet]
[Queryable(AllowedQueryOptions = AllowedQueryOptions.Supported | AllowedQueryOptions.Expand)]
public IQueryable<Muscle> Muscles()
{
return _contextProvider.Context.Muscles;
}
When I removed this line:
[Queryable(AllowedQueryOptions = AllowedQueryOptions.Supported | AllowedQueryOptions.Expand)]
It worked like a charm,
Jay thanks for all the help :)

Does verite Timeline perform well with huge data sets?

I need to visualize a huge set of data inside a timeline. I found 'verite Timeline' looks promising but I don't have any experience with it, using really many data sets. Is here anyone who could tell me about the performance of this tool or tell me about a better solution?
thnx!
As stated in their FAQ ( fourth question ):
How many entries will work best in TimelineJS?
Timeline is optimized for up to 100 entries preferably more like 20-30. Anything else may cause a loading issue.
Now maybe you could not respect their limit, but I do not think that using it with "lots of tons of data" would be a good experience. :) ( well, you could load only 100 entries at a time, but I'll leave this up to you )
I'm not able to suggest you an alternative, sorry.
Sorry ..
again, but in English ....
Verite timeline supports JSON as a data source, I have a project in MVC3 and route the data source to a controller. You obviously can do it differently for instance from a Web Service, or Ria, etc ....
To start the timeline you, put a timeline initial script in the head or body:
var timeline = new VMM.Timeline();
timeline.init("http://localhost:9306/TimeLine/Json");
You create classes to store the data structure, this will allow you to return the instance of the class in the same format json from the driver:
public class json
{
public timeLine timeline
{
get;
set;
}
}
public class timeLine
{
public string headline { get; set; }
public string type { get; set; }
public string startDate { get; set; }
public string text { get; set; }
public asset asset { get; set; }
public List<date> date { get; set; }
}
public class asset
{
public string media { get; set; }
public string credit { get; set; }
public string caption { get; set; }
}
public class date
{
public string startDate { get; set; }
public string endDate { get; set; }
public string headline { get; set; }
public string text { get; set; }
public asset asset { get; set; }
}
The controller:
public ActionResult Json()
{
json j = new json();
j.timeline = new timeLine();
j.timeline.headline = "TimeLine";
j.timeline.type = "default";
j.timeline.startDate = DateTime.Now.Year + "," + DateTime.Now.Month;
j.timeline.text = "<p>Time Line de todo el contenido.</p>";
j.timeline.asset = new asset();
j.timeline.asset.media = "";
j.timeline.asset.credit = "Desarrollador por Mauricio Farias www.ald.cl mfarias#ald.cl";
j.timeline.asset.caption = "Develop By Mauricio Farias";
j.timeline.date = new List<date>();
//for each de tiempos
for (int i = 0; i < 20; i++)
{
date d = new date();
d.startDate = DateTime.Now.Year + "," + DateTime.Now.Month + "," + i;
d.endDate = DateTime.Now.Year + "," + DateTime.Now.Month + "," + (i + 1);
d.headline = "Headline date for date in timeline";
d.text = "<p>text in date for date in timeline</p>";
d.asset = new asset();
d.asset.media = "";
d.asset.credit = "credit in asset for date in timeline";
d.asset.caption = "caption in asset for date in timeline";
j.timeline.date.Add(d);
}
return Json(j, JsonRequestBehavior.AllowGet);
}
At the hearing or in your case may be an aspx or html page (remember to put the css):
<div id="timeline">
</div>
<script src="../../Content/assets/js/timeline-min.js"></script>
<script src="../../Content/assets/js/script.js"></script>

Categories