rails 6 active storage add custom column - ruby-on-rails-6

In Rails 6 I have a model named post:
# post.rb
class Post < ApplicationRecord
has_many_attached :uploads
end
This model uses active storage. Is there a possibility to add a custom column (e.g. active: boolean) to the active storage 'uploads'?
I would like to avoid the detour via an 'upload' model.
My goal would be that e.g. this query is possible:
post.uploads.first.active
Thanks,
Andreas

Related

SetPermission With sensenet API - version 6.3

I am working on sensenet API. I faced an issue with setPermission on sensenetAPI security.
As per concern, when I create a document I would like to give See, open, Save and RunApplication permission as a default for newly created document to the user(User is taken from the function parameter).
To achieve this I use below code
public static void SetCollabUserSecurity(string myUserEmailId, Node myNodetToSetSecurity)
{
var domainName = "Builtin";
var strUsername = GetNameFromEmail(myUserEmailId);
User user;
using (new SystemAccount())
{
user = User.Load(domainName, strUsername);
if (user != null && user.Enabled)
{
var myUser = user;
myNodetToSetSecurity.Security.SetPermission(myUser, true, PermissionType.See,
PermissionValue.Allow);
myNodetToSetSecurity.Security.SetPermission(myUser, true, PermissionType.Open,
PermissionValue.Allow);
myNodetToSetSecurity.Security.SetPermission(myUser, true, PermissionType.Save,
PermissionValue.Allow);
myNodetToSetSecurity.Security.SetPermission(myUser, true, PermissionType.RunApplication,
PermissionValue.Allow);
}
}
}
While I am using this function, my process for creating document becomes time consuming. It takes around 40 second time for execution.
So in case of, if I would like to share the same newly created document with multiple users, lets say there are 3 user and I want to give the above permission to all of them then my single function call takes 120 second (2 minute) time to simply assign permission.
Is there any Odata REST API call available or any sensenet library call available through which I can assign...
1) multiple permission to multiple user for single document or
2) multiple permission to single user for single document
Can anyone help to come out from this issue?
Thanks!
C# api
On the server there is a c# api for managing permissions, please check this article for details. You may use the AclEditor class for setting multiple permissions in one round. Please note that you have to call the Apply method at the end to actually perform the operation.
// set permissions on folder1, folder2 and file1 for two users and a group
SecurityHandler.CreateAclEditor()
.Allow(folder1.Id, user1.Id, false, PermissionType.Open, PermissionType.Custom01)
.Allow(folder2.Id, user2.Id, false, PermissionType.Open)
.Allow(file1.Id, editorsGroup.Id, false, PermissionType.Save)
.Apply();
As a side note: in most cases it is better to work with groups than users when assigning permissions. So it is advisable to give permissions to a group and put users into the group as members instead of assigning permissions to users directly.
Also: it is easier to maintain a simpler security structure, for example if you assign a permission on the parent container (e.g. a folder) instead of on individual files. Of course if you have to set permission per file, then it is fine.
OData api
The same api is available from the client through the REST api. Please take a look at the SetPermissions action in this article or the similar api in the JavaScript client library of sensenet.

How to create an image database for HP IDOL OnDemand?

For Image-recognition, we require to send 'enum' as a parameter.
The description says that is a parameter for Image-database.
How to create such a database ?
Thanks
At the time of this response (I work for HPE Haven OnDemand), it is not currently possible to create your own image database with this API. The API is currently in Preview release, and uses the provided default corporatelogos public dataset. For a list of corporate logos used in the training set for the API, see Corporate Logo Training Set.

Query CMSPlugin model for draft or live objects

I've got a CMSPlugin & a request to display it's items in another app.
Obviously for every plugin you create there is a live and draft version, so doing audio = Audio.objects.all() brings you duplicate instances.
How would you go about creating a query which only returns the plugin objects from public pages?
My plugin;
class Audio(CMSPlugin):
"""
Model for storing audio clips.
"""
caption = models.CharField(
_("Title"),
max_length=255,
blank=True
)
audio_track = models.FileField()
description = models.CharField(
_("Description"),
max_length=255,
blank=True,
null=True
)
How about something like this:
Audio.objects.filter(placeholder__page__publisher_is_draft=False)
This assumes all Audio plugins belongs to a CMS page. CMSPlugins are not guaranteed to have a page associated with them! Unless you set page_only option to True:
page_only = True
Docs: http://django-cms.readthedocs.org/en/latest/reference/plugins.html#page-only

How do I disable local role acquisition after a workflow transition?

Using the Intranet workflow, and when the user selects the hide transition to move the content to the private state, I want to disable local role acquisition. I think I'll want to re-enable when they move it back to internal draft.
I can see how this is done by the sharing view within plone.app.workflow. It has a method, update_inherit, that sets context.__ac_local_roles_block__ to either True or None.
How might I do something similar with a transition after_script?
Plone 4.1.5
plone.app.workflow 2.0.6
More info on my use case:
We have two users, contributor_1 and contributor_2, possessing only the Member role globally. At the site root, create a folder and assign the two users local roles to add, edit, and view.
Here is the default private state/manage_permissions:
If contributor_1 creates a page and tries to hide it, contributor_2 can still view, edit, and transition it back to internal draft because contributor_2 is inheriting those local roles.
Here is what I first tried:
While this does effectively make the page private to only contributor_1 and any Manager, contributor_1 cannot share access with contributor_2 while the item is in the private state. No private collaboration. UPDATE: contributor_1 can manipulate the sharing view (ie. they have access to delegate local roles), but delegating those local roles (Contributor, Editor, Reader) does not translate to their respective access since I have revoked the role-permission mapping in the above workflow.
Now, if set back to the default permission map, users can achieve the private state they want by hiding the content item and then going to the sharing tab and disabling local role acquisition. The problem is they don't want to have to remember to click the checkbox on the sharing tab every time they want to hide something.
As SteveM already commented, the workflow tool can handle this for you.
You need need to manage all the necessary permission with your workflow, this depends on your needs.
UPDATE: You workflow has to manage the "Delegate Roles XYZ [Reader/Contributor/etc.]" and "Change local roles" permissions. This way the user "contributor_1" can delegate roles in the "Private" area.
Do NOT acquire any permission settings on your hidden state.
In your case the Owner (probably the manager too) needs some permissions to view/edit/changestate.
Another hint for defining workflows.
Check this package it generally manages all the permissions in action groups, like View (View, Access content permissions, etc) or Add (Add Folders, Add portal content, Add..., etc.) All Plone default permissions are mapped to the right action group, and it let's you create a workflow within 5 minutes. The best part is, you can write the workflow in human readable specification file (custom DSL).
I created a utils.py module within my package containing one method: a (nearly) straight copypasta of the update_inherit method the sharing view uses. Then, I imported utils in my package's __init__.py.
from AccessControl import Unauthorized
from AccessControl.SecurityInfo import ModuleSecurityInfo
from Acquisition import aq_base
from Products.CMFCore import permissions
from Products.CMFCore.utils import getToolByName
security = ModuleSecurityInfo( 'united.policy.utils' )
security.declarePublic('update_inherit')
def update_inherit(context, status=True, reindex=True):
"""Enable or disable local role acquisition on the context.
Returns True if changes were made, or False if the new settings are the
same as the existing settings.
"""
portal_membership = getToolByName(context, 'portal_membership')
if not portal_membership.checkPermission(permissions.ModifyPortalContent,
context):
raise Unauthorized
block = not status
oldblock = bool(getattr(aq_base(context), '__ac_local_roles_block__',
False))
if block == oldblock:
return False
if block:
# If user has inherited local roles and removes inheritance, locally
# set roles he inherited before to avoid definitive loss of access
# (refs #11945)
user = portal_membership.getAuthenticatedMember()
context_roles = user.getRolesInContext(context)
global_roles = user.getRoles()
local_roles = [r for r in context_roles if r not in global_roles]
if local_roles:
context.manage_setLocalRoles(user.getId(), local_roles)
context.__ac_local_roles_block__ = block and True or None
if reindex:
context.reindexObjectSecurity()
return True
Then, I created two scripts within my ./profiles/default/workflows/intranet_workflow/scripts/ directory bound to their respective transitions:
after_hide.py
## Script (Python) "after_hide"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=review_state
##title=
##
from united.policy.utils import update_inherit
update_inherit(review_state.object, False)
after_show.py
## Script (Python) "after_show"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=review_state
##title=
##
from united.policy.utils import update_inherit
update_inherit(review_state.object, True)

Programicatlly visit (all) ASP.Net page(s) in a website?

In the Security model for out ASP.Net website (.Net 3.5) we store the page name:
page.GetType().Name
as the primary key in a database table to be able to lookup if a user has access to a certain page. The first time a page is visited this record is created automatically in the database.
We have exported these database statements to insert scripts, but each time a new page gets created we have to update the scripts, not a huge issue, but I would like to find an automated way to do this.
I created an attribute that I tagged a few pages with and then wrote a small process to get all the objects that have this attribute, through the reflection create an instance and insert the record using the same code to for page records mentioned above:
IEnumerable<Type> viewsecurityPages = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsDefined(typeof(ViewSecurityAttribute),false));
foreach (Type t in viewsecurityPages)
{
object obj = Activator.CreateInstance(t, false);
//clip..(This code just checks if the record already exists in the DB)
if (feature == null)
{
Attribute attb = Attribute.GetCustomAttribute(t, typeof(ViewSecurityAttribute));
if (attb != null)
{
CreateSecurableFeatureForPage((Page)obj, uow, attb.ToString());
}
}
}
The issue is that page.GetType().Name when the page goes through the actual page cycle process is something like this:
search_accounts_aspx
but when I used the activator method above it returns:
Accounts
So the records don't match the in the security table. Is there anyway to programtically "visit" a webpage so that it goes through the actual page lifecycle and I would get back the correct value from the Name parameter?
Any help/reference will be greatly appreciated.
Interesting problem...
Of course there's a (too obvious?) way to programmatically visit the page... use System.Net.HttpWebRequest. Of course, that requires the URI and not just a handle to the object. This is a "how do we get there from here?" problem.
My suggestions would be to simply create another attribute (or use that same one) which stores the identifier you need. Then it will be the same either way you access it, right?
Alternatively... why not just use a 3rd party web spider/crawler to crawl your site and hit all the pages? There are several free options. Or am I missing something?

Resources