I am trying to set rules that will allow only users to create and update folders in this path: UsersMedia/folderName , where folderName is the userId .
Then I would like to not allow uploads to any other path in the Storage other then this.
service firebase.storage {
match /b/{bucket}/o {
// first rule
match /{allPaths=**} {
allow write: if false;
allow delete: if false;
}
match /UsersMedia/{userId} {
allow create, update: if (request.auth.uid == userId) && resource.size < 25000 * 1024; //25Mb;
allow delete:if false;
allow read;
}
This works only if i set the first rule to allow write, if I remove the first rule it won't work at all.
Also, the rule of the size and the userId just won't take place, so i can upload files larger than the max.
What's happening ?
Turns out the first rule will take over the other rules.
So I removed it.
Then I had a mistake and I fixed it with :
if (request.auth.uid == userId) && request.resource.size < 25 * 1024 * 1024;
To limit file size.
Now it all works.
Related
I have the following code in storage rules , but I cannot get it to work right, I need to prevent storing items other than pngs in to storage ? , but it is erroring out.
// Add to storage
allow write:
if request.auth != null // Authorized
&& request.auth.uid == userId // Owner
&& request.resource.size < 1 * 1024 * 1024 // Uploaded item must be less than 1mb !
&& request.resource.contentType.matches('image/.*'); // only image !!
// && request.resource.contentType.matches('image/.png'); // only PNG !!
try with .png or .PNG. It checks if the filename ends with .png
// Add to storage
allow write:
if request.auth != null // Authorized
&& request.auth.uid == userId // Owner
&& request.resource.size < 1 * 1024 * 1024 // Uploaded item must be less than 1mb !
&& request.resource.contentType.matches('image/.*'); // only image !!
&& request.resource.name.matches(".*\\.png"); // only PNG !!
i need to restrict the creating and editing of sys_category entries to certain category mounts for user oder usergroups.
More precise: a given backend user should be able to create a new category but not anywhere in the category treee but only under a certain category mount. And he should not be able to delete or edit categories which are not under his category mount.
Please note: i don't mean displaying only branches of category trees in other records like news. I do mean creating and editing sys_category records.
Is there a possibility?
Thanks!
Register 2 new Hooks:
// Check record while creating categories
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][]
= \JWeiland\SitePackage\Hooks\CheckCategoryRecords::class;
// Check record while moving categories
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'][]
= \JWeiland\SitePackage\Hooks\CheckCategoryRecords::class;
Add the file for Hook:
class CheckCategoryRecords
{
public function processDatamap_beforeStart(DataHandler $dataHandler): void
{
$context = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class);
$groups = $context->getPropertyFromAspect('backend.user', 'groupIds');
if (
array_key_exists('sys_category', $dataHandler->datamap)
&& is_array($dataHandler->datamap['sys_category'])
&& !empty($dataHandler->datamap['sys_category'])
&& !$this->getBackendUserAuthentication()->isAdmin()
) {
// Hook is only valid, if a record is saved and editor has no admin rights
foreach ($dataHandler->datamap['sys_category'] as $uid => $categoryRecord) {
if (!isset($categoryRecord['pid'])) {
continue;
}
//...add further conditions, if needed...
if (!in_array($groupUidWithCategoryRights, $groups, true)) {
// Add further condition, if category is allowed for given parent column
// editor is not allowed to add or move categories
unset($dataHandler->datamap['sys_category'][$uid]);
$dataHandler->log(
'sys_category',
$uid,
1,
0,
1,
'You are not allowed to create or move categories'
);
}
}
}
}
}
In my rule, I want to ensure that the data.id field is the hash of the doc id. The following is not working.
function hashGood(a, b) {
let x = hashing.sha256(a);
return x == b;
}
match /users/{userId} {
allow create: if request.auth != null && hashGood(userId, request.resource.data.id);
}
I have also tried hashing.sha256(a.toUtf8()).toBase64() and variations thereof.
When I try to create /users/B in the 'Rules Playground', it shows x == "B" . But x should be the hash of "B", not equal to "B".
What I am doing wrong?
Edit: I am using rules_version = '2';
hashing.sha256(a).toHexString() worked for me.
Though I would like to still understand why
let x = hashing.sha256(a) prints x=<value of a>
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;
Is there any way to avoid users to input line-breaks in UIInputs?
Do not want the user to be able to write line-breaks in username inputs, for example.
I searched for multiline attribute but it seems it only exists in UILabel objects.
Tried "validation:Username" but this option does not allow to write characters like "-", which is a valid username character of my application.
Thanks!
You can similarly limit your input field to a single line by setting the Max Lines property to 1 on the UILabel.
http://www.tasharen.com/forum/index.php?topic=6752.0
Had to check the UIInput.cs file to know how to ignore newlines, and I found this:
case KeyCode.KeypadEnter:
{
ev.Use();
bool newLine = (onReturnKey == OnReturnKey.NewLine) ||
(onReturnKey == OnReturnKey.Default &&
label.multiLine && !ctrl &&
label.overflowMethod != UILabel.Overflow.ClampContent &&
validation == Validation.None);
if (newLine)
{
//Insert("\n");
}
else
{
UICamera.currentScheme = UICamera.ControlScheme.Controller;
UICamera.currentKey = ev.keyCode;
Submit();
UICamera.currentKey = KeyCode.None;
}
return true;
}
So in order to avoid newlines, you need to do:
UILabelObject.multiLine = false;
UIInputObject.onReturnKey = UIInput.OnReturnKey.Default;
Doing that, bool newLine becomes false and performs Submit();