Hello every one i wanna create an command which sends an email to the admin containing the modification / deletion report + access in a table (use the data in the log file) can someone help me please
for example this is my observer it log the actions in a file so how can i make a command which sends an email to the admin containing this actions from the log file ?
public function created(AppKey $appKey)
{
Log::channel('obsinfo')
->info("id : ".$appKey->id." type : ".$appKey->type." , datetime : ".now()." operation :Creation , ip :".\Request::ip()." userAgent: ".\Request::server('HTTP_USER_AGENT'));
return true;
}
Related
TL;DR: What Database.FileFormat constant should I use for an MS Access 2000-2003 database, when creating the Database object?
I have built a SAMBA test application using jCIFS. It allows me to create/overwrite files if given the correct authentication credentials, regardless of on which PC in the domain I use it.
I also have an application that uses uCanAccess/jackcess to connect to an MDB on a network share. However (from what I understand), it uses the credentials of the logged-in user, a number of whom have read-only access. Only system/network administrators have write permission.
The database in question is not password-protected. (I don't need to enter a password when opening it.)
My intention is to have the app ask for the administrator's Samba credentials before it writes to the DB, using those in the uCanAccess connection, so that it doesn't throw a java.nio.channels.NonWritableChannelException, as per the below stack trace:
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:747)
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:310)
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:247)
at com.healthmarketscience.jackcess.impl.TableImpl.writeDataPage(TableImpl.java:1980)
at com.healthmarketscience.jackcess.impl.TableImpl.addRows(TableImpl.java:2229)
at com.healthmarketscience.jackcess.impl.TableImpl.addRow(TableImpl.java:2067)
at net.ucanaccess.converters.UcanaccessTable.addRow(UcanaccessTable.java:44)
at net.ucanaccess.commands.InsertCommand.insertRow(InsertCommand.java:101)
at net.ucanaccess.commands.InsertCommand.persist(InsertCommand.java:148)
at net.ucanaccess.jdbc.UcanaccessConnection.flushIO(UcanaccessConnection.java:315)
at net.ucanaccess.jdbc.UcanaccessConnection.commit(UcanaccessConnection.java:205)
at net.ucanaccess.jdbc.AbstractExecute.executeBase(AbstractExecute.java:217)
at net.ucanaccess.jdbc.Execute.execute(Execute.java:46)
at net.ucanaccess.jdbc.UcanaccessPreparedStatement.execute(UcanaccessPreparedStatement.java:228)
at myapp.db.Digger.addTransaction(Digger.java:993)
at myapp.tasks.TransactionRunnable.run(TransactionRunnable.java:42)
at java.lang.Thread.run(Thread.java:745)
Update: I have tried using the smbFileChannel class by Gord Thompson and J. T. Alhborn, shown here. My code, based off the main class shown in that answer, looks like this:
// Ask the user for login credentials and the path to the database
String smbURL = (chosenDir.endsWith("/") ? chosenDir : chosenDir + '/')
+ dbName;
System.out.println("DB Path to use for URL: " + smbURL);
URL u = new URL(smbURL);
try (
// construct the SMB DB URL
SmbFileChannel sfc = new SmbFileChannel(smbURL);
Database db = new DatabaseBuilder().setChannel(sfc)
.setFileFormat(Database.FileFormat.GENERIC_JET4).create();
) {
// Model the table
Table tbl = new TableBuilder("Transactions")
.addColumn(new ColumnBuilder("TransactionID", DataType.LONG).setAutoNumber(true))
.addColumn(new ColumnBuilder("ControllerID", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("ReaderID", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("Event", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("Timestamp", DataType.SHORT_DATE_TIME).setAutoNumber(false))
.addColumn(new ColumnBuilder("Number", DataType.LONG).setAutoNumber(false))
.addIndex(new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME).addColumns("TransactionID").setPrimaryKey())
.toTable(db);
// Add the row
Map<String, Object> values = new HashMap<>();
values.put("ControllerID", cid);
values.put("ReaderID", rid);
values.put("Event", evtNum);
values.put("Timestamp", ts); // Long; must be converted to DataType.SHORT_DATE_TIME
values.put("Number", accNum);
tbl.addRowFromMap(values);
} catch (IOException IOEx) {
System.err.println(
"Failed to write record to Transactions table in database: "
+ IOEx.getMessage()
);
IOEx.printStackTrace(System.err);
} catch (Exception ex) {
System.err.println(
'[' + ex.getClass().getSimpleName() + "]: Failed to write record to "
+ "Transactions table in database: " + ex.getMessage()
);
ex.printStackTrace(System.err);
}
Executing the above code results in the following output:
DB Path to use for URL: smb://machine.vpnName/Storage/me/dbs/DBName.mdb
Failed to write record to Transactions table in database: Logon failure: account currently disabled.
jcifs.smb.SmbAuthException: Logon failure: account currently disabled.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:546)
at jcifs.smb.SmbTransport.send(SmbTransport.java:663)
at jcifs.smb.SmbSession.sessionSetup(SmbSession.java:390)
at jcifs.smb.SmbSession.send(SmbSession.java:218)
at jcifs.smb.SmbTree.treeConnect(SmbTree.java:176)
at jcifs.smb.SmbFile.doConnect(SmbFile.java:911)
at jcifs.smb.SmbFile.connect(SmbFile.java:957)
at jcifs.smb.SmbFile.connect0(SmbFile.java:880)
at jcifs.smb.SmbFile.open0(SmbFile.java:975)
at jcifs.smb.SmbFile.open(SmbFile.java:1009)
at jcifs.smb.SmbRandomAccessFile.<init>(SmbRandomAccessFile.java:57)
at jcifs.smb.SmbRandomAccessFile.<init>(SmbRandomAccessFile.java:42)
at samba.SmbFileChannel.<init>(SmbFileChannel.java:30)
at samba.SambaLanWriteTest.writeTest(SambaLanWriteTest.java:130)
at samba.SambaLanWriteTest.main(SambaLanWriteTest.java:181)
I have write access to a test copy of the database file in question when using Windows File Explorer. I am choosing that one when prompted.
Update 2: I realised that I neglected to add my username and password to the smb:// URL, as Thompson's example shows. I changed to code to this:
String smbCred = "smb://" + auth.getUsername() + ":" + auth.getPassword() + "#",
fixer = chosenDir.replace("\\", "/").replace("smb://", smbCred),
smbURL = fixer + dbName;
System.out.println("DB Path to use for URL: " + smbURL);
// URL u = new URL(smbURL);
The next problem I had was that my password contains special illegal characters (such as '#', ':', ';', '=' and '?'). I escaped these by using java.net.URLEncoder.encode() on auth.getUsername() and auth.getPassword() so the code doesn't throw a MalformedURLException when creating the SmbChannel. However, the next exception I encountered is as follows:
Failed to write record to Transactions table in database: File format GENERIC_JET4 [VERSION_4] does not support file creation for null
java.io.IOException: File format GENERIC_JET4 [VERSION_4] does not support file creation for null
at com.healthmarketscience.jackcess.impl.DatabaseImpl.create(DatabaseImpl.java:444)
What Database.FileFormat constant should I use for an MS Access 2000-2003 database, when creating the Database object?
It turns out that I needed to use Database.FileFormat.V2000.
After that, it was all plain sailing (although I still need to work out how to get the Long timestamp to convert correctly).
I have a code which asks user to upload a file. The file may be audio or image or anything. I asks user to enter file name. If he Enter file name my code adds extension to it. It is working fine. But if user enters extension say audio.mp3 then it saves as audio.mp3.mp3. So I have to check if user entered name contains dot then it should not take extension.
I used pregmatch but it is not working.
My code
$splitOptions = explode(',',$request->input('mediaName'));
$fileExtension = pathinfo($file[$i]->getClientOriginalName(),PATHINFO_EXTENSION);
$checkExtension = explode('.',$request->input('mediaName'));
if(preg_match("/[.]/", $checkExtension)){
$mediaName = $splitOptions[$i];
}
else
{
$mediaName = $splitOptions[$i]."_$fileExtension";
}
Please use laravel helper
$value = str_contains('This is my name', 'my');
// true
I am about to go into the next plan in mixpanel for having too many people and would like to delete some old users first.
Is there a simple way/script/api to bulk delete old users?
I've written two scripts that may come in handy; mixpanel-engage-query and mixpanel-engage-post.
Using the first script (query) you can query your People Data and get a list of profiles, e.g. all users who have $last_seen set to a date older than X months.
Using the second script (post) you can perform actions in batch on those profiles, for example deleting them. See the README for an example of how to perform a batch delete.
Yes there is. Looking at the HTTP spec you'll find the following.
$delete
string Permanently delete the profile from Mixpanel, along with all of
its properties. The value is ignored - the profile is determined by
the $distinct_id from the request itself.
// This removes the user 13793 from Mixpanel
{
"$token": "36ada5b10da39a1347559321baf13063",
"$distinct_id": "13793",
"$delete": ""
}
Batch requests
Both the events endpoint at http://api.mixpanel.com/track/ and the profile update endpoint at http://api.mixpanel.com/engage/ accept batched updates. To send a batch of messages to an endpoint, you should use a POST instead of a GET request. Instead of sending a single JSON object as the data query parameter, send a JSON list of objects, base64 encoded, as the data parameter of an application/x-www-form-urlencoded POST request body.
// Here's a list of events
[
{
"event": "Signed Up",
"properties": {
"distinct_id": "13793",
"token": "e3bc4100330c35722740fb8c6f5abddc",
"Referred By": "Friend",
"time": 1371002000
}
},
{
"event": "Uploaded Photo",
"properties": {
"distinct_id": "13793",
"token": "e3bc4100330c35722740fb8c6f5abddc",
"Topic": "Vacation",
"time": 1371002104
}
}
]
Base64 encoded, the list becomes:
Ww0KICAgIHsNCiAgICAgICAgImV2ZW50IjogIlNpZ25lZCBVcCIsDQogICAgICAgICJwcm9wZXJ0aWVzIjogew0KICAgICAgICAgICAgImRpc3RpbmN0X2lkIjogIjEzNzkzIiwNCiAgICAgICAgICAgICJ0b2tlbiI6ICJlM2JjNDEwMDMzMGMzNTcyMjc0MGZiOGM2ZjVhYmRkYyIsDQogICAgICAgICAgICAiUmVmZXJyZWQgQnkiOiAiRnJpZW5kIiwNCiAgICAgICAgICAgICJ0aW1lIjogMTM3MTAwMjAwMA0KICAgICAgICB9DQogICAgfSwNCiAgICB7DQogICAgICAgICAiZXZlbnQiOiAiVXBsb2FkZWQgUGhvdG8iLA0KICAgICAgICAgICJwcm9wZXJ0aWVzIjogew0KICAgICAgICAgICAgICAiZGlzdGluY3RfaWQiOiAiMTM3OTMiLA0KICAgICAgICAgICAgICAidG9rZW4iOiAiZTNiYzQxMDAzMzBjMzU3MjI3NDBmYjhjNmY1YWJkZGMiLA0KICAgICAgICAgICAgICAiVG9waWMiOiAiVmFjYXRpb24iLA0KICAgICAgICAgICAgICAidGltZSI6IDEzNzEwMDIxMDQNCiAgICAgICAgICB9DQogICAgfQ0KXQ==
So the body of a POST request to send the events as a batch is:
data=Ww0KICAgIHsNCiAgICAgICAgImV2ZW50IjogIlNpZ25lZCBVcCIsDQogICAgICAgICJwcm9wZXJ0aWVzIjogew0KICAgICAgICAgICAgImRpc3RpbmN0X2lkIjogIjEzNzkzIiwNCiAgICAgICAgICAgICJ0b2tlbiI6ICJlM2JjNDEwMDMzMGMzNTcyMjc0MGZiOGM2ZjVhYmRkYyIsDQogICAgICAgICAgICAiUmVmZXJyZWQgQnkiOiAiRnJpZW5kIiwNCiAgICAgICAgICAgICJ0aW1lIjogMTM3MTAwMjAwMA0KICAgICAgICB9DQogICAgfSwNCiAgICB7DQogICAgICAgICAiZXZlbnQiOiAiVXBsb2FkZWQgUGhvdG8iLA0KICAgICAgICAgICJwcm9wZXJ0aWVzIjogew0KICAgICAgICAgICAgICAiZGlzdGluY3RfaWQiOiAiMTM3OTMiLA0KICAgICAgICAgICAgICAidG9rZW4iOiAiZTNiYzQxMDAzMzBjMzU3MjI3NDBmYjhjNmY1YWJkZGMiLA0KICAgICAgICAgICAgICAiVG9waWMiOiAiVmFjYXRpb24iLA0KICAgICAgICAgICAgICAidGltZSI6IDEzNzEwMDIxMDQNCiAgICAgICAgICB9DQogICAgfQ0KXQ==
Both endpoints will accept up to 50 messages in a single batch. Usually, batch requests will have a "time" property associated with events, or a "$time" attribute associated with profile updates.
Using the Mixpanel-api python Module
pip install mixpanel-api
This script will delete any profile that hasn't been seen since January 1st, 2019:
from mixpanel_api import Mixpanel
mixpanel = Mixpanel('MIXPANEL_SECRET', token='MIXPANEL_TOKEN')
deleted_count = mixpanel.people_delete(query_params={ 'selector' : 'user["$last_seen"]<"2019-01-01T00:00:00"'})
print(deleted_count)
Replace MIXPANEL_SECRET and MIXPANEL_TOKEN with your own project tokens.
Install Mixpanel Python API (Click Here)
pip install mixpanel-api
Create a python file : delete_people.py and copy and paste below code and perform changes as per your project configuration, i.e secret,token, filter params etc.
from mixpanel_api import Mixpanel
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%Y_%m_%d_%H_%M_%S")
if __name__ == '__main__':
#Mixpanel Project :
credentials = {
'API_secret': '<Your API Secret>',
'token': '<Your API Token>',
}
# first we are going to make a Mixpanel object instance
mlive = Mixpanel(credentials['API_secret'])
# Mixpanel object with token to delete people
ilive = Mixpanel(credentials['API_secret'],credentials['token'])
#Prepare parameters for delete condition
#<filter_by_cohort_here> - Get from mixpanel explore UI, from engage api xhr call (https://mixpanel.com/api/2.0/engage)
parameters = {'filter_by_cohort':'<filter_by_cohort_here>','include_all_users':'true','limit':0}
# Backup data before deleting
print("\n Creating backup of data\n")
mlive.export_people('backup_people_'+current_time+'.json', parameters)
# Delete people using parameters filter
print("\n Backup Completed! Deleting Data\n")
ilive.people_delete(query_params=parameters)
print("\n Data Deleted Successfully\n")
Run below command from terminal
python delete_people.py
Note: people_delete method of mixpanel api will automatically create backup_timestamp.json file in same directory where you put this script
My question is relatively the same than the one posted on developerworks forum (forum is read only due to migration) wich is :
I have a http adapter that interfaces with external web services. Part
of the payload is audio, and images. We're hitting a form size limit.
Please see attached exception at end of this post. I've read on
previous posts that jetty configurations need to be adjusted to
accommodate the larger payload. We want to control this size limit at
the server side application layer, and thought that of creating a
jetty-web.xml to define the max form size:
400000
In Worklight is this the proper approach to resolve this issue?
If this is the proper approach can you provide details whether the
jetty-web.xml should be placed under server/conf, or does it need to
be under WEB-INF of the application war?
If the file needs to be placed under WEB-INF can you explain how to
accomplish this file being placed under WEB-INF during the WL project
build.
Thanks E: Ajax request exception: Form too large802600>200000
2013-02-06 11:39:48 FWLSE0117E: Error code: 1, error description:
INTERNAL_ERROR, error message: FWLSE0069E: An internal error occurred
during gadget request Form too large802600>200000, User Identity
{wl_authenticityRealm=null, GersServiceAdapterRealm=(name:USAEMP4,
loginModule:GersServiceAdapterLoginModule),
wl_remoteDisableRealm=(name:NullLoginModule,
loginModule:NullLoginModule), SampleAppRealm=null,
wl_antiXSRFRealm=(name:antiXSRF, loginModule:WLAntiXSRFLoginModule),
wl_deviceAutoProvisioningRealm=null, WorklightConsole=null,
wl_deviceNoProvisioningRealm=(name:device,
loginModule:WLDeviceNoProvisioningLoginModule),
myserver=(name:3e857b6a-d2f6-40d1-8c9c-10ca1b96c8df,
loginModule:WeakDummy),
wl_anonymousUserRealm=(name:3e857b6a-d2f6-40d1-8c9c-10ca1b96c8df,
loginModule:WeakDummy)}.
I have exactly the same problem :
I send a large amount of data to a worklight adapter and my application fail with the following error message into the log :
2013-08-21 09:48:17] FWLSE0020E: Ajax request exception: Form too large202534>200000
[2013-08-21 09:48:18] FWLSE0117E: Error code: 1, error description: INTERNAL_ERROR, error message: FWLSE0069E: An internal error occurred during gadget request Form too large202534>200000, User Identity {wl_authenticityRealm=null, wl_remoteDisableRealm=(name:null, loginModule:NullLoginModule), SampleAppRealm=null, wl_antiXSRFRealm=(name:b2isf3704k2fl8hovpa6lv9mig, loginModule:WLAntiXSRFLoginModule), wl_deviceAutoProvisioningRealm=null, WorklightConsole=null, wl_deviceNoProvisioningRealm=(name:40a24da9-0a32-464a-8dec-2ab402c683ae, loginModule:WLDeviceNoProvisioningLoginModule), myserver=(name:2b1a7864-37c4-47f0-9f5c-49621b6915b5, loginModule:WeakDummy), wl_anonymousUserRealm=(name:2b1a7864-37c4-47f0-9f5c-49621b6915b5, loginModule:WeakDummy)}.
This occurs on calling an adapter procedure by calling WL.Client.invokeProcedure(...) and before the first line of the called procedure... If I try to log the start of the called procedure I have nothing written in my debug log...
I can give you my source code :
This one is called by a dhtml user event (onclick) :
// Construct the param to pass to the WL adapter insert procedure
var paramObject = {
QCDART: machine, // machine is a javascript variable as long int
QTITRE: title, // title is a javascript variable as string(255)
QDESC: desc, // desc is a javascript variable as string(255)
QHODAT: todayDateDb2IntFormat, // todayDateDb2IntFormat is a javascript variable as long int
QACTIF: active, // active is a javascript variable as int
SSRCFIC: currentPdfFileDataBase64, // currentPdfFileDataBase64 is a javascript variable as base64 encoded string from a binary file > 150 ko approx.
SMIMFIC: 'application/pdf',
SSIZFIC: currentPdfFileSize // currentPdfFileSize is a javascript variable as long int
};
// Construct adapter invocation data
var invocationData = {
adapter : 'IseriesDB2Backend', // adapter name
procedure : 'addModeleReleves', // procedure name
parameters : [paramObject] // parameters if any
};
WL.Client.invokeProcedure(invocationData, {
timeout: 60000,
onSuccess: function() {
// Notify success
alert('OK');
}, // invokeProcedure success callback
onFailure: function(invocationResult) {
alert('ERROR');
} // invokeProcedure failure callback
});
This one is my adapter source code :
var addModeleReleveStatement = WL.Server.createSQLStatement("select QCDDOC from FINAL TABLE (insert into ERIHACFICH.DOCENTQ (QCDART, QTITRE, QDESC, QHODAT, QACTIF) values (?, ?, ?, ?, ?))");
function addModeleReleves(params) {
WL.Logger.debug('Starting adapter procedure...');
var modeleReleveResult = WL.Server.invokeSQLStatement({
preparedStatement : addModeleReleveStatement,
parameters : [params.QCDART, params.QTITRE, params.QDESC, params.QHODAT, params.QACTIF]
});
if(modeleReleveResult.isSuccessful) {
WL.Logger.debug('Success !');
}
WL.Logger.debug('Adapter procedure ended !');
// Return result (with the last id inside)
return modeleReleveResult;
}
if the javascript varable called currentPdfFileDataBase64 is small, all is working normally but if it exceeds approximatively 200000 chars length it fails...
Last, I ca say that the problem occurs in development environment (WL Studio 5.0.6 + WL Server 5.0.6), I didn't test it on the production environment based on SLES + Websphere application server 7 + worklight.
Thanks for any help
I understand you are using the test server provided by Worklight.
It looks like this is a Jetty limitation so you could try any of these:
1) Set the system property org.eclipse.jetty.server.Request.maxFormContentSize to a bigger value (i.e. adding -Dorg.eclipse.jetty.server.Request.maxFormContentSize=25000000) to the end of eclipse.ini before launching Worklight.
or
2) Instead, set this other system property -Dorg.mortbay.jetty.Request.maxFormContentSize=25000000 to the same place.
Another way to solve the problem was to use WL Studio version 6 that doesn't use Jetty anymore as test environment
I have written a code using procedure to send an email in Jython. Now I have put my procedure inside a package and I am running the package.
However, what I need to get is the package name, start time of execution of package and end time of execution of package and send it via email.
I tried using getPrevStepLog but that isn't working
My procedure code as of now:
import smtplib
import string
BODY = string.join((
"From: %s" % 'test#gmail.com',
"To: %s" % 'admin#odi.com',
"Subject: %s" % 'Mail From ODI',
"",
'This is a mail from ODI Studio. Thank You.Previous step
'<%=odiRef.getPrevStepLog("STEP_NAME")%>' executed in
'<%=odiRef.getPrevStepLog("DURATION")%>' seconds'
), "\r\n")
sender = smtplib.SMTP('smtp.gmail.com',587)
sender.set_debuglevel(1)
sender.ehlo()
sender.starttls()
sender.ehlo()
sender.login('test', 'test123')
sender.sendmail('test#gmail.com',['admin#odi.com'],BODY)
sender.close()
Have you try to use the function getSession ?
public java.lang.String getSession(java.lang.String pPropertyName)
pPropertyName
SESS_NO = internal session ID
SESS_NAME = session name
SCEN_VERSION = version of current scenario
CONTEXT_NAME = name of the execution context
CONTEXT_CODE = code of the execution context
AGENT_NAME = name of the physical agent
SESS_BEG = date and hour of the begining of the session
USER_NAME = Oracle Data Integrator user executing the session
Exemple : to get the current session name
<%=odiRef.getSession("SESS_NAME")%>