I've recently deleted 120,000 Users from my Liferay database using an automated script. Before that however, I manually deleted 2 Users from the database using DELETE FROM User_ WHERE userId=1234567 - just to see what might happen with any associations that User might have had.
The User was deleted, but all other table rows holding that userId (1234567) remained. Fine.
So now I'm at a point where I'd like to reindex all search indexes to get a current list of users, but LR throws an exception:
08:07:41,922 ERROR [http-bio-20110-exec-290][LuceneIndexer:136] Error encountere
d while reindexing
com.liferay.portal.kernel.search.SearchException: com.liferay.portal.NoSuchUserE
xception: No User exists with the key {contactId=1234568}
at com.liferay.portal.kernel.search.BaseIndexer.getDocument(BaseIndexer.j
ava:179)
at com.liferay.portlet.usersadmin.util.ContactIndexer$1.performAction(Con
tactIndexer.java:203)
at com.liferay.portal.kernel.dao.orm.BaseActionableDynamicQuery.performActions
InSingleInterval(BaseActionableDynamicQuery.java:309)
at com.liferay.portal.kernel.dao.orm.BaseActionableDynamicQuery.performActi
This contactId seems to be a single digit higher than the userId for any user created (I could be wrong about that)
So my question is, how can I fix this problem so I can perform the reindex?
Liferay EE 6.2
Tomcat 7.0.33
SQL Server
I found out the contactId for my manually deleted user was still in the Contact_ Table. I deleted him from the table and can now perform the reindex. I can now see all the user & user groups after reindexing.
From LR:
rule #1 with using Liferay - The database is not yours, you should
never be in it and you should never be issuing sql against it.
The Liferay API is the only way to modify data. Period.
The Liferay API supports user deletion. Had you used the Liferay API,
the users would have been deleted and your indexes, etc., would have
been fine.
Okay, I know that's going to come across as a little aggressive or
something, but it's important. The whole Liferay system depends upon
it's data, so any time you tweak the data manually it potentially
breaks the system. If you dig through the actual process that the
Liferay API does for a user deletion, you'd see that the "delete from
user_ where ..." is just a small part.
I always tell people new to Liferay to just forget that the database
exists. It's definitely their database, not yours, and it's not to be
messed with.
Related
before write the question sorry for my english. My question is this:
I have an web application in jsf, the application have new, edit and delete Categories, outgoings, Budgets, users, etc.
When open the edit page i have the url like this:
http://localhost:8080/Practica3/faces/usuarios/edit.xhtml?id=2
the problem is if the user change the number 2 for another number, and the another number exists in the dababase, the page change the data of the id 2 to the data of the new id.
The problem is if the id number X is of a data of another user, and the user that change the id is not in conditions to see that data.
How disable the edit of the id, or denied to show the data to the another user?
Thanks, and i hope have a response.
Just check in service layer if the current user is allowed to edit the requested entity. If not, then throw some security exception for which you could if necessary configure a custom error page in web.xml.
The technical problem has nothing to do with HTTP/JSF. If you "fix" it alone in JSF side, then you still have a gaping security hole in service layer which would affect any other frontend using it. The frontend is not responsible for business restrictions in service layer itself.
The problem is not stopping the editing of the ID. That is on the client side/browser and you cannot stop this value from being edited.
You need to implement propery Access Security Controls. When you get any response back, you need to check if the user can perform the action they specified (read, update, delete, etc.) as well as checking to make sure they have permission to the data they want to perform the action on.
These two topics are on the OWASP Top 10:
A4-Insecure Direct Object References
A7-Missing Function Level Access Control
The pages will tell you what the problem is, mitigation stragegies, and different ways of testing for that in your application.
I would also become familiar with the other Top 10 categories (this is not an all inclusive list but a good starting point).
I have a mobile app using Couchbase lite. When the user logouts, I want to remove some of the documents on the device; the user-specific documents. I do not want to remove all of the documents. Documents have a purgeDocument() method that I thought I could call on those user-specific documents.
The problem is that the purged documents are not re-synced down to the device if the user logs back in and a pull replication is run.
Based on the little I know of CouchDB sync protocol, it makes sense that those are not re-synced down because there are not newer Sequence updates on those user-specific documents to trigger a re-sync.
How should I approach this problem?
Possibilities
Delete the whole database (including common documents) and lose performance.
Somehow reset the last sequence for the replicator and hope the replicator does not transfer the already-downloaded docs over the wire. (Probably would screw up CBL)
Have separate databases, one that stores the user-specific docs and one that contains common docs. Databases can have filtered replicators (by channel) so it would be feasible to partition the incoming data into separate databases. The problem would be the seamless reference loading between documents of differing databases when using CBLModel objects wrappers.
As i understand from the official documentation in the subsection Purging documents, you are not retrieving the document again just because it has not been modified/updated (in short, its rev is the same) on the server side.
You can try to create again a dummy document with the same type and, for example, username (or whatever you are using to identify the user's configuration) when the user logs again in your app so that you trigger the pull replication from the server. You probably will have a conflict that can easily be solved taking the revision from the server.
I hope this idea helps a little.
UPDATE AFTER COMMENT
The idea is to store somewhere the id and type of the user's documents you're going to purge. That way you can create a new dummy document with those two fields when the user logs in again. Perhaps this new dummy document triggers the pull replication.
NOTE: I haven't tried this method. I am just guessing what it might be a work around to your problem.
I would suggest that your backend modifies the selected documents - this could be just a timestamp update - upon user login, which will post the new revisions to the device
You can keep purging the documents when the user logs in.
To solve problem of re-syncing specific document, I think the easiest way is to use filtered replication where the filter is document id.
These document IDs can be created in a manner which can be derived. For example it can be as UserDocument::.
Now when the user logs in you can start one shot replication with document ID as filter. This can only be done in one shot. And when this One Shot finishes you can start replication again by changing the setting of the replication(changing filter/channel).
following is the URL by Couchbase which explains filtered replication by document ID.
https://developer.couchbase.com/documentation/mobile/1.4/guides/couchbase-lite/native-api/replication/index.html#filtering-by-document-ids
Try Push after Purging the document with Couchbase Lite which allows you to Pull the document from the server at a later point.
I am new to Liferay. Now I need to create the flow chart which has the Liferay table work flow in following scenarios,
1) What are the list of table will reflect/update if we create the site admin?
2) What are the list of table will reflect/update if we create the site?
I tried by opening database tables and noticed that USER_, CONTACT_ will reflect, But I need list of all the related tables which will reflect when we create the site and siteadmin? I am using Liferay 6.2 version.
Thanks in advance.
When you want to know the internals of any system it is always best to check the relevant source-code. So in this case you can check the source-code for those classes which are used for CRUD operations on User and Site.
1) What are the list of table will reflect/update if we create the site admin?
Site-administrator is a Role, which can be applied to a User created in Liferay.
So if you want all the tables that are created from User-creation till User is assigned the Site-administrator role for a particular site, there here are some which I can recollect:
User_ (Obvious)
Contact_ (not so obvious :-) )
Group_ (Users are also created as a record in this table since Users have public and private pages)
Address (if you add an address)
Phone (if you add a Phone)
Users_Roles (Power user role is assigned by default)
UserGroupRole (user and site-role relationship, Site-administrator is a Site-role)
Users_Groups (user and site relationship)
For others you should refer the source-code for UserLocalServiceImpl, RoleLocalServiceImpl and GroupLocalServiceImpl, check the relevant methods prefixed add, update etc.
The corresponding service.xml for these module would reveal the database tables being used.
2) What are the list of table will reflect/update if we create the site?
Sites are nothing but Groups in Liferay. So its obvious Group_ table is playing a big role.
Other tables also depend upon what configuration you are doing while creating a Site.
Then there would be other tables like Layout when you start creating pages for a Site.
I would strongly encourage to go ahead and explore the source code for the classes and you would understand the flow - when and what tables are affected.
Here is some convention which might help you traverse the source-code, almost every *LocalServiceImpl is associated with a *Model like UserLocalServiceImpl with UserModel and almost every *Model has a corresponding database table with the same name.
Also the name of the functionality would in most cases hints at what service classes are being used to connect to database, like adding a User would hint at using UserLocalServiceImpl.
Hope I have understood your question and have been able to give some proper direction.
If you want to know this because you also want to write to these tables: Don't go there! You should purely use the API to change the data that Liferay stores. Otherwise you will run into disasters some time in the future - promised.
For just getting the SQL commands that Liferay actually uses, configure portal-ext.properties and change this default value:
hibernate.show_sql=false
Then go to "Server Administration/Log Levels" and add a new category "org.hibernate.SQL", configure it to the level DEBUG. Then the results show up in the logs. Note that this log configuration is transient and will be reverted on next server start. If you want the setting to be persistent, you'll need to go into Liferay's log4j configuration files.
Remember: You don't want to write to the tables ever. Promise!
Currently I develop a database for another employee at my company. I have Manager Rights at the database to access everything. The administrator of the database should only be able to create/edit/delete documents. He currently got Editor-Access with selected "delete documents"-option. When he wants to delete a document on the database (i tried it with Simple Actions or with Javascript Code-both don't work) he gets redirected to the same page and nothing happens or with Simple Actions the Server-Login page shows up with the message "You don't have the permission to perform this action".
When im testing the functions with my manager access everything works fine. But when i'm changing my rank to Editor like the normal administrator of the database i also can't delete any documents. Like i already said the option in the ACL is activated.
I hope you can understand my problem and there is a solution for it. Normally that access right works fine on every other database at our company.
Another point: There are no Reader or Editor fields in the Documents. So there is no restriction with fields. Could this be the problem?
Check to see if there is some code in the QueryDocumentDelete event for the database. Perhaps that is failing and / or preventing you from deleting.
Given that you mention redirecting and server login, I presume it's a web enabled database?
In which case have you tried looking at the ACL (Access Control List) for the problem database and clicking the Advanced tab.
In there is a field Maximum Internet name and password, this is the maximum access allowed for internet users. If it's not editor, this could be the problem?
Try deleting with ?DeleteDocument URL. That way it will for sure not try to do anything else.
Check the user's access level at server with Database.getCurrentAccessLevel() and Database.queryAccessPrivileges(String name)
After the great suggestions of you all the problem was the checkbox "Allow document locking" at the database properties was enabled. That caused the problems at deleting documents. As Manager is have enough rights to go over that but for the normal Administrator with Editor Access the deletion request got blocked by the little option.
Thanks to everyone!
The administrator of the web application I am working on, asks for a 'I wanna know everything' log. He wants to track all what the other users did when they were connected (logged in) to the web app :
What pages he/she visited.
What actions he/she performed.
On what entities (JPA Entities) he/she performed actions.
At what exact time she/he performed a given action if successful.
What attribute of the a given record he/she modified.
The user principals of this user.
All I could do now, is export a CSV file where the administrator finds the user principals, the time this user logged in and logged out.
I also created an example history table in database populated by EclipseLink Customizer to track changes for a corresponding table. (The problem with this EclipseLink customizer is that it is not flexible, because database tables are changing with time (adding/removing attributes) and so are their corresponding entities. And the user does not want to modify things two times (one time in the main table and the second time in the history table)!
Could something like a third library 'log4j' do that?
Is there any alternatives, solutions, or better practices related to my issu!?
Best regards.
Look into Interceptors/Listeners - both for JSF to get page/action and JPA to get data accessed. In your interceptors/listener you could then log to file using log4j.
EclipseLink Listeners
Hibernate Interceptors (for comparison)
JSF Listeners