For example I have this implementation of the assert method in the class derived from Zend_Acl_Assert_Interface.
function assert(
Zend_Acl $acl,
Zend_Acl_Role_Interface $user = null,
Zend_Acl_Resource_Interface $item = null,
$privilege = null
) {
if (!$user instanceof User) throw new Exception("…");
if (!$item instanceof Item) throw new Exception("…");
return
$user->money >= $item->price &&
$user->rating >= $item->requiredRating;
}
It checks two conditions: user has enought money and user has enought rating. How to display error message to make user know which condition is failed when isAllowed method returns only bool?
simply check them one by one
$error = array();
if(!($user->money >= $item->price))
$error[] = "user money is less then price";
if(!($user->rating >= $item->requiredRating))
$error[] = "user rating less then required rating ";
Zend_Registery::set('acl_error',$error);
if(count($error) == 2) return false;
return true;
you can retrieve acl errors anywhere in your applicating by Zend_Registry::get('acl_error') ; and show it to user as you like.
Related
I'm trying to create a Security Rule based upon request.time as given in an example on AngularFirebase website.
My function is
function isThrottled() {
return request.time < resource.data.lastUpdate + duration.value(1, 'm')
}
Where I'm trying to allow update: if isThrottled() == false
However, when I try to update a document with this rule, it fails due to time being not defined on the object.
Error: simulator.rules line [169], column [12]. Property time is
undefined on object.
Shouldn't every request have a time or TimeStamp attached to it? Is this something to do with how I'm initializing my Cloud Functions or client app?
Screenshots below:
EDIT
A snippet for the rest of the update security rules are:
service cloud.firestore {
match /databases/{db}/documents {
match /users/{userId} {
match /username/{id} {
allow update: if isSelf(userId)
&& usernameAvailable(incomingData().username)
&& incomingData().username is string
&& incomingData().username.size() <= 25
&& incomingFields().size() == 1
&& isThrottled() == false;
}
}
function incomingData() {
return request.resource.data
}
function isThrottled() {
return request.time < resource.data.lastUpdate + duration.value(1, 'm')
}
function incomingFields() {
return incomingData().keys()
}
function isSelf(userId) {
return userId == currentUser().uid;
}
function usernameAvailable(username) {
return !exists(/databases/$(db)/documents/usernames/$(username));
}
}
}
The username collection is a subcollection under each user document (in the users root collection. Each username document only has 1 field called username that users can update).
This might not be useful for your case in particular, but I had the same error when checking a custom claim on the token object.
Before accessing the field you can use in to check whether the property exists on the object. This code generates the error if agent is not defined:
allow write: if request.auth != null && request.auth.token.agent == true;
This code works fine if agent is not defined:
allow write: if request.auth != null && "agent" in request.auth.token && request.auth.token.agent == true;
I have custom obj "A" and Standard obj Case. Case standard obj has lookup to custom obj "A". there is a field between the two objects called Customer_ID__c. I wrote a Trigger (before Insert, Before Update) to associated the case record to the correct existing custom obj "A" record if "Case.Custom_Id__c" match the one in the Custom obj "A". Unfortunate it is not happening and I'm not sure where to look.
trigger IAACaseRelateASAP on Case (before insert, before update) {
Id recordtypes = [Select Id, name
From RecordType
Where SobjectType = 'Case'
AND Name = 'I Buy'
LIMIT 1].Id;
Set<String> casId = new Set<String>();
for(Case cs : Trigger.new)
{
if(cs.RecordtypeId == recordtypes && cs.Type == 'Contact Me')
{
if(cs.custm_Obj_A_Name__lookupfield__c == null && (cs.Customer_ID__c != null || cs.Customer_ID__c !='0'))
{
casId.add(cs.Customer_ID__c);
}
}
}
system.debug('Case Set Ids' + casId);
List<A__c> aList = [Select Customer_ID__c, Id
From A__c
Where Customer_ID__c IN: casId
AND
A__c != 'Provider'];
System.Debug('equals' + aList);
Map<String, A__c> aMapId = new Map<String, A__c>();
for(A__c aAcct : aList)
{
aMapId.put(aAcct.Customer_ID__c, aAcct);
}
for(Case cas : Trigger.new)
{
if(cas.RecordtypeId == recordtypes && cas.Type == 'Contact Me')
{
if(cas.custm_Obj_A_Name__lookupfield__c == null && (cas.Customer_ID__c != null || cas.Customer_ID__c !='0'))
{
if(aMapId.containsKey(cas.Customer_ID__c))
{
A__c aAcct = aMapId.get(cas.Customer_ID__c);
System.Debug('Case IAA ASAP Account value: ' + asapAcct);
}
}
}
}
}
It might be best when looping through your cases to build your set of Customer_ID__c ids to also build a List of cases with customer ids so that you don't have to loop through the entire new list a second time. There are a couple other issues with the trigger in general but I'll ignore those and just focus on what you asked. Think your issue is that you don't actually set the case field in this area:
if(aMapId.containsKey(cas.Customer_ID__c))
{
A__c aAcct = aMapId.get(cas.Customer_ID__c);
System.Debug('Case IAA ASAP Account value: ' + asapAcct);
}
It should be :
if(aMapId.containsKey(cas.Customer_ID__c))
{
cas.custm_Obj_A_Name__lookupfield__c = aMapId.get(cas.Customer_ID__c).Id;
}
Inside my User model I would like to make a isMember function.
public function isMember()
{
return(\Auth::check() && "get the status value here" == 1)
}
I got two models. User, Club.
Their pivot table: club_user
user_id
club_id
status
The 'status' column holds 0 or 1.
Now, how do i check the value for the extra column 'status'?
Update:
It's a many-to-many relationship.
Try This:
public function isMember(){
if(\Auth::check())
return (bool) $this->status;
return false;
Well, I got it to work. If somebody got some suggestions how to make it better, please fell free.
public function isMember($clubId)
{
$user = Club::find($clubId)->user()->where('club_user.user_id', \Auth::id())->first();
if (is_object($user))
{
$status = $user->pivot->status;
else
{
$status = 0;
}
return (\Auth::user() && $status == 1);
}
I'm trying to create trigger if record type is Revenue Risk then amount should be saved in negative value, Here's my code in which I'm having error, I tried it two ways, second is in comments.. none of them is working
public with sharing class amountValidator {
//pull data of Opportunity in list
public static void validateAmount (list<Opportunity> oppList){
oppList = [Select amount FROM Opportunity WHERE RecordType.Name IN ('Revenue Risk')];
for(Opportunity opportunities : oppList){
if(oppList.amount >= '0'){
oppList.amount = oppList.amount * '-1';
}
}
/*Map<String,Schema.RecordTypeInfo> rtMapByName = d.getRecordTypeInfosByName();
Schema.RecordTypeInfo rtByName = rtMapByName.get('Revenue Risk');
for(Opportunity each : oppList){
if(rtByName.size == 0){
}
else{
if(oppList.Amount >= 0){
oppList.Amount = oppList.Amount*-1;
}
}
}*/
The error is very clear:
if(oppList.amount >= '0'){ // THIS LINE WILL THROW AN ERROR: 'Comparison arguments must be compatible types: Integer (or Double), String
oppList.amount = oppList.amount * '-1'; // THIS ONE TOO: 'Arithmetic expressions must use numeric arguments'
}
Your second code snippet is also wrong (same for first one).
if(oppList.Amount >= 0){
oppList.Amount = oppList.Amount*-1;
// MUST BE each.Amount = each.Amount * - 1; Please try not to use reserved words as variable names
}
You may want to take a look at a previous post describing strongly typed programming languages: Strongly Typed
Since we can't add comments just yet, we're going to add a new answer:
You're not updating/inserting the updated amount for your opportunity.
The correct way of doing this is to create a separate List of Opportunities (i.e. List oppsToUpdate) and add the updated opportunities to this list.
public static void validateAmount (list<Opportunity> oppList){
oppList = [Select amount FROM Opportunity WHERE RecordType.Name IN ('Revenue Risk')]; // Why are you requerying the Opportunity if you already have it??
List<Opportunity> oppsToUpdate = new List<Opportunity>();
for(Opportunity opportunities : oppList){
if(opportunities.amount > 0){
opportunities.amount = opportunities.amount * -1;
oppsToUpdate.add(opportunities);
}
}
upsert opportunities;
}
Remember to enclose your function with try-catch statements with system debugs to see what's going on with your code.
And this is the link to the input parameter modifications and why this is bad practice: Input Parameters
Working Code:
trigger Risk_NegativeQuantity on OpportunityLineItem (before insert) {
set<id> oppid = new set<id>();
for (OpportunityLineItem oli : trigger.new)
{
oppid.add(oli.opportunityid);
}
Id RevenueRisk= Schema.SObjectType.Opportunity.getRecordTypeInfosByName().get('Revenue Risk').getRecordTypeId();
list<opportunity> opplist = [select id, recordtype.name,recordtypeid from opportunity where id in : oppid ];
for (OpportunityLineItem oli : trigger.new)
{
for (opportunity opp: opplist)
{
if (oli.opportunityid == opp.id)
{
if(opp.recordtype.name == 'Revenue Risk')
{
if(oli.Quantity > 0)
{
oli.Quantity = oli.Quantity * -1;
}
}
}
}
}
}
I am getting a null refrence exception when im filtering EF but I am absolultely clueless.
public IEnumerable<TonalityBatchModel> GetTonalityBatch(int briefID)
{
try
{
var brief = NeptuneUnitOfWork.Briefs.FindWhere(b => b.ID == briefID).FirstOrDefault();
if (brief != null && brief.TonalityCriteria != null)
{
return brief.TonalityCriteria.TonalityBatches
.Select(b => new TonalityBatchModel()
{
BriefID = b.BriefID,
Status = b.TonalityCriteria.IsActive == true ?"Active":"Ended",
BatchID = b.ID,
CompetitorID = b.BriefCompetitorID,
Competitor = brief.BriefCompetitors.Where(i=>i.ID == b.BriefCompetitorID).Select(c=>c.Organisation.Name).First(),
Size = b.BatchSize,
StartDate = b.StartDate,
EndDate = b.EndDate,
IsPublished = b.Lookup_TonalityBatchStatus.ID == (int)TonalityBatchStatus.Published?"Yes":"No",
IsCompleted = b.Lookup_TonalityBatchStatus.ID == (int)TonalityBatchStatus.Completed ? "Yes" : "No",
IsAssigned = b.Lookup_TonalityBatchStatus.ID == (int)TonalityBatchStatus.Allocated ? "Yes" : "No",
ImportantCount = b.TonalityItems.Count(i=> i.IsImportant),
ArticlesCount = b.TonalityItems.Count,
FavourableCount = b.TonalityItems.Count(i => i.Lookup_TonalityScoreTypes.ID ==(int)TonalitySourceType.Favourable),
UnfavourableCount = b.TonalityItems.Count(i => i.Lookup_TonalityScoreTypes.ID ==(int)TonalitySourceType.Unfavourable),
NeutralCount = b.TonalityItems.Count(i => i.Lookup_TonalityScoreTypes.ID ==(int)TonalitySourceType.Neutral)
}).ToList();
}
return new List<TonalityBatchModel>();
}
catch (Exception ex)
{
Logger.Error(ex);
throw;
}
}
You'll need to reduce your query to a simpler query, and then start building it back up again until the NullReferenceException occurs. Looking at your code, here are some likely places (I'm making some assumptions since I don't know everything about your model):
Competitor = brief.BriefCompetitors.Where(i=>i.ID == b.BriefCompetitorID).Select(c=>c.Organisation.Name).First()
BriefCompetitors could be null. c.Organisation could be null.
IsPublished = b.Lookup_TonalityBatchStatus.ID == (int)TonalityBatchStatus.Published?"Yes":"No",
(and other similar lines) b.Lookup_TonalityBatchStatus might be null.
ImportantCount = b.TonalityItems.Count(i=> i.IsImportant),
(and other similar lines) b.TonalityItems might be null.
I believe this is because your count is returning null records. I could be wrong but the SQL that's being produced here is something like:
INNER JOIN TonalityItems i on i.Lookup_TonalityScoreTypes == x
Where x is the value of (int)TonalitySourceType.Favourable. Because this join has no matching results there is nothing to do a count on. You could try adding ?? 0 to the end of the query:
FavourableCount = b.TonalityItems.Count(i => i.Lookup_TonalityScoreTypes.ID ==(int)TonalitySourceType.Favourable) ?? 0,