ORACLE APEX CREATE LOGON TRIGGER - oracle11g

I want to update a status to my table with specific criteria (where clause) when any user logs on..
create or replace TRIGGER AUTO_COMPLETE
AFTER LOGON ON SCHEMA
BEGIN
UPDATE SESSIONS
SET SESSIONS.STATUS = 5
WHERE SESSIONS.STATUS =2
AND TO_CHAR(SESSIONS.SESSION_DATE, 'MM-DD-YYYY HH24.MM') < TO_CHAR (SYSDATE, 'MM-DD-YYYY HH24.MM');
END AUTO_COMPLETE;
Unfortunately this trigger is not fired and i have no errors!!

Apex is stateless, see first paragraph here. That means that a new database session is created for every page render or post process. I think that would make that logon trigger fire constantly when the user navigates around the application.
You could create an application process with point "After Authentication" in your application. That will fire only once for the application after the user authenticates.
Keeping this functionality separate from your database makes sense. A logon trigger will fire when you connect through sqldeveloper or over rest as well - and it will affect performance.

I think the best way is in your app settings, you can user bind variables to verify the username or another stuff.
Shared components / Security Attributes / Database Session
Or another option is to create a process after authentication

Related

Informix - capture user ID in delete trigger

I have an ASP.NET (C#) web application that connects to Informix 12.x database. The web application uses a database connection string with username and password. Users are given login accounts to use the web application and they can delete records in the database.
The database tables have "LastModifiedBy" which contains the user ID. Now, I need to implement auditing using database triggers. I need to capture what records were updated or deleted and who did it (i.e. logged in user) and save these in an audit table.
For the delete trigger, how can I capture the user ID of the logged in user and save this in the audit table?
The database user (available via the keyword USER) is always going to be the username associated with the shared database credentials. Your question is not very clear, but are you saying the existing LastModifiedBy attribute contains the named user or the database user? If it's the named user, I think you should probably look at your ASP.NET code to see how that gets passed into the UPDATE statement.
I'm no expert on ASP.NET, but assuming a single page request uses the same database connection throughout its processing cycle, then you could maintain a table keyed on the session ID, available via DBINFO('sessionid'), where you capture the named user at the top of the request, and then you have it available at any point throughout the process for inclusion in your audit. But if the web-server processes are using a pool of database connections and any statement could go to a different connection, even that won't work.
Ultimately, I don't think database triggers are the right solution here, not least because you'll have to write and maintain a trigger for every table in your application. If I was faced with this problem I would be more inclined to have a common Audit function within the web-app, where the named user is always available.
At the OP's request, a bit more detail. The Session ID is exactly the same concept as you see in SSMS - just a unique number that identifies the connection.
Imagine you have the following table and procedures:
CREATE TABLE session_user (
sessionid INTEGER NOT NULL,
username VARCHAR(20),
conn_date DATE,
PRIMARY KEY (sessionid)
);
CREATE PROCEDURE set_user(v_username VARCHAR(20))
UPDATE session_user SET username = v_username, conn_date = TODAY
WHERE sessionid = DBINFO('sessionid');
IF DBINFO('sqlca.sqlerrd2') = 0 THEN
INSERT INTO session_user VALUES (DBINFO('sessionid'), v_username, TODAY);
END PROCEDURE;
CREATE PROCEDURE get_user()
DEFINE v_username VARCHAR(20);
SELECT username INTO v_username
FROM session_user
WHERE sessionid = DBINFO('sessionid');
IF v_username IS NULL THEN
LET v_username = USER;
-- return system user if no record found in session_user table
END IF;
RETURN v_username;
END PROCEDURE;
NB: None of this code is tested, it's just to show the principle. I don't have an Informix instance to hand to test this on.
At the top of the request, however you execute your SQL, you would run:
EXECUTE PROCEDURE set_user($the_web_user);
Your triggers could then use get_user() wherever you want to capture that info. You'll get the actual web user if it's been recorded in the session_user table, otherwise the database user (which will be the shared database credentials if the triggering DML has come from the web-app, or the physically logged in user if the trigger is via a DB-Access session).
I still don't think this is a particularly maintainable solution - every table needs its own trigger(s). An OO audit method in the web-app would be a more DRY approach, or have a look at Informix's preexisting audit capabilities.
Note: the date field was included in the session_user table so you run a clean-up over it, because depending on how often new connections get created by the web-app, your session_user table could grow like topsy.

is Workflow Management right required to create SG with Workflow Process defined?

We are noticing that if a user without Workflow Management rights on a Publication tries to create a Structure Group and sets the "Associated Page Process" set on the Workflow tab, they get a permission error. If the workflow setting is removed, the user can save without issue.
I assume this is by design in the product, right? I wanted to verify that we weren't hitting something in our custom code. If it matters, here's what's logged:
Unable to save Structure Group (tcm:0-0-0). You do not have permission to perform this action. Error Code: 0x80040242 (-2147220926) Call stack: Tridion.ContentManager.Security.AuthorizationManager.AssertAccess(IdentifiableObjectData,Permissions,Rights) Tridion.ContentManager.CommunicationManagement.StructureGroup.OnSaving(SaveEventArgs) Tridion.ContentManager.IdentifiableObject.Save(SaveEventArgs) Tridion.ContentManager.IdentifiableObject.Save() Tridion.ContentManager.BLFacade.ContentManagement.RepositoryLocalObjectFacade.Create(UserContext,String) XMLState.Save StructureGroup.Save
thanks,
~Warner
Yes, to assign a Workflow Process Definition to an item (Schema or SG), you need Workflow Management rights.

alfresco-access application query filtering not working on 4.0.e

I have created application which is accessing alfresco using web service client. Now I want to audit all events of that application in alfresco, so I have enabled alfresco-access audit application. Here when I execute simple audit query it is returning all results properly, but when I execute query to get all audit events related to specific file it returning 0 entries.
Simple Query to get all audit events
http://localhost:8080/alfresco/service/api/audit/query/alfresco-access?verbose=true
Advanced Query to only get audit events of specific file
http://localhost:8080/alfresco/service/api/audit/query/alfresco-access/transaction/path?verbose=true&value="/app:company_home/cm:test/cm:test1/cm:test2/cm:testfile.pdf"
I have added following configuration in my alfresco-global.properties:
audit.enabled=true
audit.tagging.enabled=true
audit.alfresco-access.enabled=true
audit.alfresco-access.sub-events.enabled=true
audit.cmischangelog.enabled=true
audit.dod5015.enabled=true
audit.config.strict=false
audit.filter.alfresco-access.default.enabled=true
audit.filter.alfresco-access.transaction.user=~System;~null;.*
audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site<br>
audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.*
Following query is now working, just need to add application name in key parameter -
http://localhost:8080/alfresco/service/api/audit/query/alfresco-access/alfresco-access/transaction/path? verbose=true&value=/app:company_home/cm:test/cm:test1/cm:test2/cm:testfile.pdf

Windows Workflow - Creating a reusable task list (bookmarks?)

I'm looking at migrating business processes into Windows Workflow, the client app will be ASP/MVC and the workflows are likely to be hosted via IIS.
I want to create a common 'simple task' activity which can be used across multiple workflows. Activity properties would look something like this:
Related customer
Assigned agent
Prompt ("Please review PO #12345")
Text for 'true' button ("Accept")
Text for 'false' button ("Reject")
Variable to store result in
Once the workflow hits this activity a task should be put into a db table. The web app will query the table and show the agent a list of tasks they need to complete. Once they hit accept / reject the workflow needs to resume.
It's the last bit that I'm stuck on. What do I need to store in the DB table to resume a workflow? Given that the tasks table will be used by multiple workflows how work I instantiate the workflow to resume it? I've looked at bookmarks but they assume that you know the type of workflow that you're resuming. Do I need to use reflection or is there a method in WF where I can pass a workflow id and it will instantiate it?
You can use workflow service and control its via ControlEndPoint.
For more info about controlendpoint you can refer at
http://msdn.microsoft.com/en-us/library/ee358723.aspx

How to clear SQL session state for all users in ASP.NET

I use SQLServer SessionState mode to store session in my ASP.NET application. It stores certain objects that are serialized/deserialized every time they are used.
If I make any changes in code of the structure of those objects and I put a new version live, any logged user will get an error, as their session objects (the old version ones) do not match the structure that the new version expects while deserializing.
Is there a way to clear all sessions at once in DB so that all active sessions expire and users are forced to log in again (and therefore all session objects are created from scratch)?
Or... Is there any other way to solve this situation?
You may try using stored procedure in SQL Server to clear all the sessions:
CREATE PROCEDURE [dbo].[DeleteSessions]
AS
DELETE [ASPState].dbo.ASPStateTempSessions
RETURN 0
You can call Session.Abandon, or Clear for every user when they hit the invalid Session object.
You can also loop through the per-user Session collection, and clear the keys that can contain "old" objects. Maybe you have a login ticket and such that you don't want to clear.
foreach (string key in Session.Keys)
{
if (!key.Equals("login"))
{
Session.Remove(key);
}
}

Resources