I have an app, in which a user can create a session for themselves. By a session I mean , it has a title and a frequency (For Example - {"title": "homework" , "frequency": "MWF"} where MWF is Monday,Wednesday,Friday). I want to store the session frequency and title in my firestore database in such a way that when the user creates a new session, i fetch from firestore the possible clashes -
For example - if the user is creating a session called "homework" and an "homework" already exists then , I can tell them that a session by that name already exists OR If a user is creating a session with frequency" MTS and already has a session with the frequency MWF, then I have to tell the user that there is a possible clash. Same with creating TTF and MWF already exists, then I have to inform the user of a possible clash.
My question, is that how can i do it, given the fact that I use the firestore database?
The easiest thing to do is simply query for any documents that would conflict before you allow the user to add the conflicting document. So, if you want to find a conflict where title="homework", you would query for conflicts first:
firestore.collection("your-collection").where("title", "==", "homework")
// then check the results to see if there was a match
Firestore doesn't provide a way to stop duplicate field values in a collection, so it's still possible that somehow a user could add a conflicting document. If you need to force uniqueness of a field value within a collection, that requires much more work, which might not be worthwhile for your case.
Related
i'm making a chat app using firebase. For each document that contains any name, i'm creating it as auth.currentUser.displayName. So for example, each message in the chat is a document created as:
sender: currentUser?.displayName!,
avatar: currentUser?.photoURL!,
content: message,
time,
About changing the username, i know how to do it, but if i change my username, i would have to access all the documents of every user that contains my name and change it too. Is there a better way to do it? Like, instead of auth.currentUser.displayName, i use something like user XYZ.displayName, and if user XYZ changes its name, it will also change in every other document.
Thanks in advance
But if i change my username, i would have to access all the documents
of every user that contains my name and change it too.
This is indeed a consequence of the data modelling in a NoSQL database, where you duplicate data instead of normalizing it as you would do in a SQL database.
Is there a better way to do it?
Apart from mimicking an SQL database (having the user name in a unique user document and fetching this doc each time you want to display this user name - i.e. you mimic an SQL join) there is no other way than updating each doc containing the value of the user name.
Mimicking an SQL database means that each time you want to display a message in the chat you need to fetch the document containing the user name value (not good for cost and performance). Keeping the denormalized approach means that you need to update all the corresponding message documents only when a user name change. So, depending on the frequency of the user names updates, you can decide which one is the best.
Like, instead of auth.currentUser.displayName, i use something like
user XYZ.displayName, and if user XYZ changes its name, it will also
change in every other document.
Basically this will not make any difference since you'll have to update all the docs containing the (previous) user name.
In our web application we want to use DB2 row level access control to control who can view what. Each table would contain a column named userId which contain the user id. We want log-in users be able to see only row's usereId column with theirs id. I have seen db2 permission examples using DB2 session_id or user, for example taking DB2 given Banking example :
CREATE PERMISSION EXAMPLEBANKING.IN_TELLER_ROW_ACCESS
ON EXAMPLEBANKING.CUSTOMER FOR ROWS WHERE BRANCH in (
SELECT HOME_BRANCH FROM EXAMPLEBANKING.INTERNAL_INFO WHERE EMP_ID = SESSION_USER
)
ENFORCED FOR ALL ACCESS
ENABLE;
Our table gets updated dynamically hence we don't know what row get added or deleted hence we don't know what are all the user Id in the table.
At any given time, different user would log-on to the web to view information retrieve from the tables, the permission declaration above only take SESSION_USER as the input, can I change it to something like Java function parameter where one can pass arbitrary id to the permission? If not then how do I handle different log-in users at arbitrary time? Or do I just keep changing SESSION_USER dynamically as new user login (using "db2 set" ??)? If so then is this the best practice for this kind use case?
Thanks in advance.
Since the user ID in question is application-provided, not originating from the database, using SESSION_USER, which equals to the DB2 authorization ID, would not be appropriate. Instead you might use the CLIENT_USERID variable, as described here.
This might become a little tricky if you use connection pooling in your application, as the variable must be set each time after obtaining a connection from the pool and reset before returning it to the pool.
Check out Trusted Contexts, this is exactly why they exist. The linked article is fairly old (you can use trusted contexts with PHP, ruby, etc. now).
I have a custom object in Salesforce which I need to setup a Master Detail relationship from Accounts. Accounts being the Master and CompHist being the Detail. The problem I am running into is that I need to set the relation to work off of custom fields within the objects. Example:
1.) Accounts has a custom field called CustomerId.
2.) CompHist also has custom field called CustomerId.
3.) I need to be able to have this linked together by CustomerId field for report generation.
About 2,000 records are inserted into CompHist around the 8th of each month. This is done from a .NET application that kicks off at the scheduled time, collects info from our databases and then uploads that data to salesforce via the SOAP API.
Maybe I'm misunderstanding how Salesforce relationships work as I am fairly new (couple months) to salesforce development.
Thanks,
Randy
There is a way to get this to work without triggers that will link the records or pre-querying the SF to learn Account Ids in .NET before you'll push the CompHistories.
Setup
On Account: set the "External ID" checkbox on your CustomerId field. I'd recommend setting "Unique" too.
On CompHist: you'll need to make decision whether it's acceptable to move them around or when the relation to Account is set - it'll stay like that forever. When you've made that decision tick / untick the "reparentable master-detail" in the definition of your lookup / m-d to Account.
And if you have some Id on these details, something like "line item number" - consider making an Ext. Id. for them too. Might save your bacon some time in future when end user questions the report or you'll have to make some kind of "flush" and push all lines from .NET (will help you figure out what's to insert, what's to update).
At this point it's useful to think how are you going to fill the missing data (all the nulls in the Ext. Id) field.
Actual establishing of the relationship
If you have the external ids set it's pretty easy to tell salesforce to figure out the linking for you. The operation is called upsert (mix between update and insert) and can be used in 2 flavours.
"Basic" upsert is for create/update solving; means "dear Salesforce, please save this CompHist record with MyId=1234. I don't know what's the Id in your database and frankly I don't care, go figure this out will ya?"
If there was no such record - 1 will be created.
If there was exactly 1 match - it will be updated.
If there were more than 1 found - SF won't know which one to update and throw error back at you (that's why marking as "unique" is a good idea. There's a chance you'll spot errors sooner).
"Advanced" upsert is for maintaining foreign keys, establishing lookups. "Dear SF, please hook this CompHist up to Account which is marked as "ABZ123" in my DB. Did I mention I don't care about your Ids and I can't be bothered to query your database first prior to me uploading my stuff?"
Again - exact match - works as expected.
0 or 2 Accounts with same ext. id value = error.
Code plz
I'd recommend you to play with Data Loader or similar tool first to get a grasp. of what exactly happens, how to map fields and how to not be confused (these 2 flavours of upsert can be used at same time). Once you'll manage to push the changes the way you want you can modify your integration a bit.
SOAP API upsert: http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_upsert.htm (C# example at the bottom)
REST API: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_upsert.htm
If you'd prefer an Salesforce Apex example: Can I insert deserialized JSON SObjects from another Salesforce org into my org?
I've written a C/CGI web application for booking items. My client has requested that I add an 'admin' feature where an authorised user can delete and change data, and those who aren't, can only add data. It is much simpler in concept than most login implementations as there is only a password, and effectively only two states, 'anonymous' and 'admin'.
I come from a PHP background where session management is as simple as session_start(), and I can instantly play around with $_SESSION. Of course, in C/CGI there is nothing built-in like that. I would like to avoid adding a CGI library dependency (I already depend on glib, confuse and libmysqlclient, plus I'm curious to learn about session management).
What is the simplest way to do a password-based session management in C/CGI, without the need for multiple users, large amounts of session data, or anything complex?
A session implies server side maintained state. As you don't have users I guess you want it simpler. If that is the case a signed cookie with an expiration date can do it. This tutorial will show how to do it with Python:
http://webpython.codepoint.net/cgi_cookie
First you have to decide how you are going to persist state in the browser : are you going to use a session cookie or pass a session token on each page ? If you go with the cookie way, you don't have to change your pages and forms, but you need to add cookie management if it's not already present (be careful to use session + httpOnly cookies)
Then you must decide how to get data about the state on the server : if you're already using a database, you could add a "SESSION" table with columns "SESSION_ID" and "EXPIRATION_DATE" + a second table called "SESSION_DATA" with columns "SESSION_ID", "KEY", "VALUE".
You now "just" have to create some simple functions :
int session_createNewSession(long& session_id, long duration)
int session_setValue(long session, char[] key, char[] value)
int session_getValue(long session, char[] key, char[] value)
int session_abandonSession(long session)
This functions would return error codes if session could not be created, or value could not be set/get. You should also probably create a job that runs regularly on the database to delete older sessions.
Now that you have your session system in place, the rest is pretty straightforward :
create a login form
in your cgi handle the received data by checking if the login/password is right (don't store the passwords in the db though : store a salted hash)
if connexion is OK, save the user id in session (or in your case, you could just save a "IsAdmin" value)
You could do in fact simpler : just a session_createNewSession(long& session_id, int isAdmin) would be sufficient in your case (with only one database table), but your client is probably going to ask more features over time isn't he ?
One final note : be careful that your session_id's are random, not indent fields, otherwise it would be quite simple to hijack someone else's session.
I'm writing a site on GAE-Java + Objectify which lets users create their own pages, with unique URL. I haven't been able to figure out a clear way to ensure that when two users try to claim the same url at the same time, only one user gets it.
This is what I'm trying to avoid:
User 1 does a check - its available
User 2 does a check - its available
Meanwhile, User 1 creates page and stores it.
User 2 creates a page and overwrites User 1.
Any ideas on how to solve this on GAE?
Why not just run your code in a transaction? I don't see where the issue is. Do you have a sample of something you've tried and had problems with?
Found a clearer explanation in the python docs:
Attempts to get the entity of the model's kind with the given key name. If it exists, get_or_insert() simply returns it. If it doesn't exist, a new entity with the given kind, name, and parameters in kwds is created, stored, and returned.
The get and subsequent (possible) put are wrapped in a transaction to ensure atomicity. Ths means that get_or_insert() will never overwrite an existing entity, and will insert a new entity if and only if no entity with the given kind and name exists.
In other words, get_or_insert() is equivalent to this Python code:
def txn():
entity = MyModel.get_by_key_name(key_name, parent=kwds.get('parent'))
if entity is None:
entity = MyModel(key_name=key_name, **kwds)
entity.put()
return entity
return db.run_in_transaction(txn)