Implement Terms and Conditions for IdentityServer (something similar to Consent Service) - identityserver4

Our applications do not require consents from the users, whereas they require terms and conditions (tandc) to be accepted before accessing the application. We have two tables to track tandc, something like this:-
TersmAndConditions
-TermsAndConditionsId
-Message
-IsActive
UserTermsAndConditions
-UserId
-TermsAndConditionsId
-AgreedDate
Current approach:
Every time we come up with a new tandc (which happens when there is a major change in the application), we insert a record in the TermsAndConditions table. When a user signs into our application, right after the authentication we check whether there is a record in the UserTermsAndConditions table for the authenticated user, if yes, we issue tokens, and if there is no record we show the tandc page, and when the user agrees the tandc, we insert a record into the UserTermsAndConditions table.
We're planning to do the same by coming up with a new implementation of IConsentService instead of the DefaultConsentService. Is this a right approach?

Related

Constructing a database that collects information from two public surveys and imports answers to a hidden back-end

I am fairly new to constructing databases and was hoping I could get pointed in the right direction on this project. I have self-taught how to use Microsoft Access (my boss is asking that I specifically use this program) and how to "build a database," but I'm stuck on the abstract, specific functions I'm expected to implement. I'll post what I have come up with from all my research to show I've attempted this on my own before asking, but I would greatly appreciate drawing from the expertise of this community. Thanks for all of your time.
Context:
There is a manager survey (1) and an employee survey (2). Every few months, we have leadership roles open up and the managers fill out a survey with all the information regarding the role (opportunity) that they will be in charge of. After all the managers answer, the hopeful employees then review all of the new opportunities, fill out their own survey with some similar questions (and others unique), and indicate what opportunity they are most interested in. Once they fill out their surveys, the data is collected and matched up to the opportunity they wrote they wanted.
My thought process:
The backend can't be editable by those taking the survey - they (managers and employees) should only be able to add a new, non-existent record to their respective table (from the info entered in their survey). The DB would be stored in a
(1) Manager fills survey out (a form created from Mgr_FormShare - a middle man table), import data to backend db table (Mgr_SurveyDataMain)
*Split DB
*Use form as front-end, "properties_data entry: yes"
*Set up relationship between table inside backend and form
(2) Employee reviews opportunities, chooses DESIRED opportunity# and fills in rest of data (in a form created from Emp_FormShare / middle-man table), import data to backend db table (Emp_SurveyDataMain)
*Split DB
*Use form as front-end, "properties_data entry: yes"
*Set up relationship between table inside backend and form
(3) Run query, imports both surveys into one table in backend (ManagerEmpCombineData)
(4) Append an Assigned field in the Mgr_SurveyDataMain (if an opportunity is discovered as chosen, it's "assigned" status goes from no -> yes)
My questions:
Is this the correct way to approach this situation? Is there something I am missing here?
Also, is there a way to ensure all surveys (about 200+ when employee + manager count) will automatically share to the middle-man + only allow one entry per individual? Before splitting, I wanted to make sure that the forms with the properties [DataEntry: "Yes", RecordsSource: "*_FormShare", Each field's control source: linked to respective *_FormShare field] would be enough to make sure that they synced. It's okay if I can't ensure only one use, the sync is the most important aspect.
Thanks again for taking the time to go through my question!

Clicks not code and Salesforce Contacts?

So I've got a group of users who originally were going to use one custom object and nothing else, and now their team wants a Case system and the whole shebang.
A Case means a Contact, which lives under the account. The Trouble is everything else these users do is driven from that one custom object they use, which isn't tied into the case system. This leaves my users with exactly the problem described here: https://www.buttonclickadmin.com/salesforce-visual-workflow-advanced-flows/
In other words, Lots and lots of extra effort to find an account, check for a contact and then either use it or make a contact.
Now, if I had a primary key (like the email) that I could count on 100% I'd use a flow like that other guy did. But I don't. Lots of the case contacts don't have email or just plain won't give it (or worse use a group email). AFAIK Record Lookups in a flow only pull one record.
I could fix this with some snazzy VisualForce + Apex. I could take the Id from that one custom object the users have and give them a custom search. I could probably tag the Contact with that Id too (I'm trying not to, it's a big org and it's a pain to get permission to update Standard Objects).
Am I missing something? Why are Case Contacts such a pain to create and manage for users? I understand that the workflow of Account -> Contact -> Case helps prevent duplicates, but it's incredibly confusing to tell my users "Don't go to the Case Tab when you want a case, find the account first".

GAE Transaction in root entity

I'm new to GAE and I have some questions about transaction with the DataStore.
For example, I have a user entity, which is created when the user adds my app on Facebook. I get some properties with the Facebook API, but I want to add a username for the user, and it needs to be unique. So in the transaction scope I call this method:
def ExistsUsernameToDiferentUser(self, user, username):
query = User.all()
query.filter("username", username)
query.filter("idFacebook != ", user.idFacebook)
userReturned = query.get()
return True if userReturned else False
But GAE gives me this error:
BadRequestError: queries inside transactions must have ancestors
Ok, I understand, but the user doesn't have any ancestor, it's a root entity. What do I have to do?
I see what you're trying to do now.
By forcing the use of ancestors, the datastore forces you to lock down a portion of the datastore (everything under the given ancestor) so you can guarantee consistency on that portion. However, to do what you want, you essentially need to lock down all User entities to query whether a certain one exists, and then create a new one, and then unlock them.
You CAN do this, just create an entity, it can be an empty entity, but make sure it has a unique key (like "user-ancestor"), save it, and make it the ancestor of every User entity.
THIS IS A PROBABLY A BAD IDEA since this limits your performance on User entities, particularly on writes. Every time a new user is created, all User entities are prevented from being updated.
I'm trying to illustrate how you need to think about transactions a bit differently in the HRD world. It's up to you to structure your data (using ancestors) so that you get good performance characteristics for your particular application. In fact, you might disagree with me and say that User entities will be updated so infrequently that it's ok to lock them all.
For illustrative purposes, another short-sighted possibility is to create multiple ancestors based on the username. ie, one for each letter of the alphabet. Then when you need to create a new User, you can search based on the appropriate ancestor. While this is an improvement from having a single ancestor (it's 26 times better), it still limits your future performance up front. This may be ok if you know right now the total number of users you will eventually have, but I suspect you want hundreds of millions of users.
The best way is to go back to the other suggestion and make the username the key. This allows you the best scalability, since getting/setting the User entity by key can be transactional and won't lock down other entities, limiting your scalability.
You'll need to find a way to work your application around this. For example, whatever information you get before the username can be stored in another entity that has a RelatedField to the User which is created later. Or you can copy that data into the User entity after the User entity is created by key, then remove the original entity.
If usernames are unique why dont you make it the key?
class User(db.Model):
#property
def username(self):
return self.key().name()
....
User.get_or_insert(username,field1=value1,....)
Note: You will not need transactions if you use get_or_insert

app engine logging to database and entity groups

In my application I have a Profile entity, which have some children, like ProfileAccount, ProfileLink, etc. They're usually updated in a transaction, like
def update_profile(key):
profile = db.get(key)
accounts = db.query("SELECT * FROM ProfileAccount WHERE ANCESTOR IS :1", profile)
# do something with accounts and profile
profile.put()
I call it with db.run_in_transaction(update_profile, key), but I need to have an administrative log of everything that happens when the profile is updated, so I created a generic AdminLog entity which contains a reference to a Profile, the timestamp and arbitrary string data. This would be processed later to check what happened since the last user login.
The problem is as AdminLog doesn't belong to the same entity group as the Profile, I cannot add it on the same transaction, but on the other side, I don't think it would be clever to put all those logs under the same entity (Profile), as it's not essential data.
One thing I thought about would be a StringList on the Profile, that would be cleared on each login, so this way I'd have everything that happened to the profile. Do you think that's a nice approach, or maybe there's some other workaround for this kind of situation ?
Thanks in advance for any tips
Using child entities seems like the best option. It ensures you can update them transactionally, and associates the changes with the entity they apply to. If you wish, you can garbage collect old admin log entries to save space.

How to structure database tables?

I am planning a database. It will track when a software program has been registered and log the information in the Registered table.
Two questions:
1: where should i log invalid registration attempts. For example if the user enters the wrong registration information or if they try to register but they have used all of their licenses. I want to remember this information but where do i put it?
I was thinking a separate FailiedRegiatration table or in general notifications table. What do you think?
2: Also if a user registers the same computer i want to allow them however i want to document that they reregistered the computer. Where should i store this information?
I was thinking making a DateRegiatered table that is linked to the Refistered table. That way for each successful registration i can keep track if someone reregisteres on the same computer.
Any comments are helpful as i think through this.
Thanks.
If you need to specifically act on failed registrations, or later activate it and make it a successful registration table, store it in a separate table. If you only need to know about it, consider just storing the failure in a log table of some sort.
I think you want a separate table tracking user, and the machine registered on; that way, you know how many registrations a user performed, whether its 1, 2, or 10, etc. Just a pointer table that points to user ID and the registration...
My two cents.
Personally, I prefer to use logs, rather than database tables, to record "events" that are suitable for logging, and your "failed registration" event definitely seems to fall under this category (the "dates of registration" information is more debatable from this point of view).
Of course, that does depend on having a good logging system (with log rotation, etc) and a good log-processing system too -- many hosting providers, for example, may not give you those, though they'll typically let you use a relational DB.
If that's the case (you can't rely on "good logging and log processing", but rather whatever you do need to persist must go s/where in the DB), then one or more "log-like tables" (more or less like you outline) are a kind-of-OK workaround (and it's hard to suggest better ones, especially without enough info about your deployment situation;-).
I think 2 tables would work. One table to track users (eg: id, username, serial, email), and one table to track registrations (id, foreign key to the users table, timestamp, record of success or failure, and some field to id the user's computer).
The second table would be your log table and have entries for successful initial reg, successful re-registration, and failed registration attempts. no?
Depending on how much information on the user's machine you have you can come up with various ways to ID if it is the same machine or not. This is a hard problem though.

Resources