Excluding properties when persisting unowned entity relation jdo (gae) - google-app-engine

In a Google App Engine app, I have this model:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Message {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private Date timestamp;
#Persistent
private String text;
#Unowned
#Persistent(defaultFetchGroup = "true")
private User sender;
...
}
The model has an #Unowned relation to a sender, since a user can exist independently of a message.
What I want to do is persist Message objects with partial User objects (e.g. I'm only interested in storing the user id and username). In my endpoint class I'm storing messages just fine, however, if I don't include all fields for the given user in the relationship, the user object is updated with the fields missing (e.g. user in question no longer has a password etc.). What is the best way of achieving what I want, without 'corrupting' the original object?
PS
My endpoints method is dead simple. Basically just calling pm.makePersistent(message); on the message (given as a method parameter).

You are using the #Unowned annotation which means that only a reference to the actual User entity will be stored in the sender variable under your Message class.
When you access the sender variable, the Datastore will execute a get query to retrieve the User entity that is linked to the message.
You can confirm this for yourself by navigating to your project's Datastore dashboard (https://console.cloud.google.com/datastore for production, and http://localhost:8080/_ah/admin for local) and browsing the Message entities.
You should see the field where the User is stored named something like user_id_OID with a value of Key(User/XXXXX).
As a side note, Google recommends moving away from JDO/JPA to Objectify or the Datastore API.
Warning: We think most developers will have a better experience using
the low-level Datastore API, or one of the open-source APIs developed
specifically for Datastore, such as Objectify. JDO was designed for
use with traditional relational databases, and so has no way to
explicitly represent some of the aspects of Datastore that make it
different from relational databases, such as entity groups and
ancestor queries. This can lead to subtle issues that are difficult to
understand and fix.
See here:
https://cloud.google.com/appengine/docs/java/datastore/jdo/overview-dn2

Related

Does deferred save in Objectify apply per Java entity or per Google Cloud Datastore entity?

Our app logic has multiple layers. Each time a save is invoked, the entity on the domain layer is mapped to a database entity.
For example:
class Sample(); // the domain entity
#Entity("Sample")
#Cache
class DatabaseSample; // the database entity
Let's assume the domain entity is modified and save is invoked, which will map all properties to a new database entity, which is then saved deferred.
Let's assume the same domain entity is modified again and saved again, which will again map all properties to a new database entity and invoke deferred save.
Will the two separate Google Cloud Datastore entities compete with each other, e.g. the newer save overwrite the older save completely, or will objectify collect modified Key-Value pairs during the request and save a consolidated entity at the end of the request?
I don't quite understand the question, but I'll try to give you some context that might help.
If you defer save of an entity POJO, it just marks it as "save this thing" in the session. When the session closes (end of transaction) anything marked for deferred save (or delete) gets saved.
Only at the very moment of saving to the datastore does the POJO get mapped to a low-level Entity. You can defer save the same object a zillion times with no practical effect. In fact, this is the core use case - you might have a method that sets changes some data and wants a save, and some other method that changes some data and wants a save... by using deferred saves, you avoid making separate real saves to the datastore.
If you're asking about doing something really crazy like changing the #Id after deferring a save... don't. I really have no idea what that will do, but you probably won't like it :-)

Variable datasource based on user

I'm currently developing a back end and having my first run in with security laws etc. and it has complicated the design of my DB slightly:
Specification
Central server for app with DB containing limited user information (user_id, email, password (hashed and salted)) can be anywhere.
Organisations making use of our service require that all other information be stored in-house, so the database for that particular organisation is in their building.
The user IDs in our central database are used by multiple types of users in these organisations databases, where more info about that user is stored (phone number, name, address...)
Problem
With Spring Boot, I need to make it so the datasource used is determined by which user makes the request. I map users to their corresponding organisation's database within the central server so the information is there, but I'm not sure how to make this variable.
I understand there are methods involving adding another database config in the application.properties file. But as far as I'm aware this can't be changed (easily) once the server is deployed and running without a full redeploy, and I'm hoping to build this in such a way that adding another organisation only involves setting up their db, and adding another database details to the central server.
Extra detail
I'd like to use CrudRepository with hibernate entities for this. I plan on only generating user IDs on the central server.
Any pointers would be awesome.
Thanks!
The terminology for this is database multi-tenancy. There are multiple strategies for multi-tenancy: different databases, different schemas in the same database, and the same schema on one database with a defined discriminator.
You basically create a DataSourceBasedMultiTenantConnectionProviderImpl class which provides the connection to a datasource based on which tenant is requesting it, and a CurrentTenantIdentifierResolverImpl class which identifies who is the requesting tenant.
You can read more about it here. Since your tenants each have their own database, you would probably want to focus on the multi-tenancy separate database approach. It worked fine with CrudRepository when I implemented it. You also might want to find your own way of creating the tenant map, since I had 2 tenants and no need to add more at any point.
Heres a sample of the connection provider from when I implemented this:
public class DataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
private static final String DEFAULT_TENANT_ID = "A";
#Autowired
private DataSource datasourceA;
#Autowired
private DataSource datasourceB;
private Map<String, DataSource> map;
#PostConstruct
public void load() {
map = new HashMap<>();
map.put("A", datasourceA);
map.put("B", datasourceB);
}
#Override
protected DataSource selectAnyDataSource() {
return map.get(DEFAULT_TENANT_ID);
}
#Override
protected DataSource selectDataSource(String tenantIdentifier) {
return map.get(tenantIdentifier);
}
}

Google App Engine. JPA. How to implement #ManyToOne without backward #OneToMany?

As I found when asking this post to have #ManyToOne association work I need to add
backward #OneToMany entity.
But after that I found that I cannot now find these entities specifying it's own id.
I need to specify also parent's id.
Here's how my id looks like:
User(1)/Issue(2)
So, I need to find in such way:
entityManager.find(Issue.class, KeyFactory.createKey(KeyFactory.createKey("User",1),"Issue",2))
And I wonder, what will be if I have several ManyToOne fields.
Please, follow me to the exact instructions on how to deal with #ManyToOne fields in GAE.

Salesforce: Is it a good idea to use SOQL to enforce security and limit record access?

This is more of a best practices question. Our org currently has "public read" permissions on our org wide defaults for custom objects. We cannot make this private because of the way its working now for internal employees or rather we are trying to avoid this.
I am also creating a customer portal with custom visual force pages...where I display data using SOQL queries.
Is it a good idea to add a clause on the SOQL query to return only those records where the account id matches the logged in user's acount id?
I did it and it works fine...But are there any pitfalls to this method that I am overlooking?
Thanks,
Calvin
Per the Visualforce Documentation
Because standard controllers execute in user mode, in which the
permissions, field-level security, and sharing rules of the current
user are enforced, extending a standard controller allows you to build
a Visualforce page that respects user permissions. Although the
extension class executes in system mode, the standard controller
executes in user mode. As with custom controllers, you can specify
whether a user can execute methods in a controller extension based on
the user's profile.
I believe the idea being, as long as your classes are public with sharing then permissions should be enforced and records should not be returned that the user cannot see (same with fields on a record).
per the Apex Documentation
Apex generally runs in system context; that is, the current user's
permissions, field-level security, and sharing rules aren’t taken into
account during code execution.
Use the with sharing keywords when declaring a class to enforce the sharing rules that apply to the current user. For example:
public with sharing class sharingClass {
// Code here
}
Use the without sharing keywords when declaring a class to ensure that the sharing rules for the current user are not enforced. For example:
public without sharing class noSharing {
// Code here
}
Otherwise you would have to spend hours ensuring that the right permissions applied at exactly the right time for the right user. It would almost completely defeat the purpose of a visualforce page!

Should I encrypt my App Engine entity keys when I export data?

I am currently exporting data from App Engine (to csv files) so that a few graduate students can analyze and build models based on the data. The data that I am exporting consists of non-confidential properties and the entity keys for a few models that DO contain confidential data (email addresses, names, etc.). My goal is to produce a dataset that can be shared and analyzed publicly without exposing any private data in the other entities that I’m sharing the keys for.
I started off planning to encrpyt all the entity keys to annonymize the data, but then I realized that the unencrypted keys might not be of any value to anyone as long as my app never exposes any data based on entity keys. My app only exposes personally indentifyable data based on the id for each entity.
Is there any reason to be concerned about sharing App Engine keys for entities? Is there anything that anonymous users can do with entity keys if there aren’t any urls that return any information based on the keys?
The entitiy keys contain the name of your app, the name of the entity (and any parents) and the numeric id of your entity.
If your app does not expose the data of the referenced entity you are okay.
Here`s the link in the google docs:
http://code.google.com/intl/de-DE/appengine/docs/python/datastore/entities.html
And more concrete docs on db.Key(): http://code.google.com/intl/de-DE/appengine/docs/python/datastore/keyclass.html
"Note: A string-encoded key can be converted back to the raw key data. This makes it easy to guess other keys when one is known. While string-encoded key values are safe to include in URLs, an application should only do so if key guessability is not an issue."

Resources