Skip to content

Commit

Permalink
- Update canvas code that pulls files from canvas. Clear read-only fl…
Browse files Browse the repository at this point in the history
…ag on files before downloading, then set read-only flag on files after downloading. This prevents students from saving a file under the original cached location.

#143
  • Loading branch information
frankyrumple committed Aug 31, 2023
1 parent 0174293 commit 1326d7b
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 94 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ exported_gpo
/media_files_tool/media_files/media
/media_files_tool/ssh.log
/client_tools/svc/mgmt.dist
/media_files_tool/sync_media_files.build
/media_files_tool/sync_media_files.dist
37 changes: 6 additions & 31 deletions client_tools/lms/src/OPE_LMS/OPE_LMS.pro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
QT += qml quick sql network quickcontrols2 webview networkauth webchannel webenginequick webenginecore webenginewidgets core5compat
#
#graphicaleffects
#webengine webenginewidgets
# networkauth
# webengine webenginewidgets quick-private webview-private webview
Expand Down Expand Up @@ -90,7 +90,7 @@ QMAKE_LFLAGS += /ignore:4042
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
# DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
#QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
Expand Down Expand Up @@ -132,34 +132,6 @@ HEADERS += \
appmodule.h \
db.h \
openetworkaccessmanagerfactory.h \
# cm/file/cm_fileinfo.h \
# cm/file/cm_syncfile.h \
# cm/file/cm_syncfilechunk.h \
# cm/file/cm_syncfileversion.h \
# cm/school/sc_classes.h \
# cm/school/sc_classmodel.h \
# cm/school/sc_lessonitem.h \
# cm/school/sc_lessonitemmodel.h \
# cm/school/sc_modulemodel.h \
# cm/school/sc_modules.h \
# cm/school/sc_programmodel.h \
# cm/school/sc_programs.h \
# cm/cm_classroom.h \
# cm/cm_database.h \
# cm/cm_httpserver.h \
# cm/cm_machine.h \
# cm/cm_mimetypes.h \
# cm/cm_persistentobject.h \
# cm/cm_persistentobjectmodel.h \
# cm/cm_screengrab.h \
# cm/cm_sequentialguid.h \
# cm/cm_users.h \
# cm/cm_webrequest.h \
# external/ex_canvas.h \
# external/ex_ldap.h \
# appmodule.h \
# db.h \
# openetworkaccessmanagerfactory.h \
cm/cm_javascripthandler.h \
cm/cm_websockettransport.h \
customlogger.h
Expand All @@ -168,6 +140,8 @@ HEADERS += \
RC_ICONS = logo_icon.ico

DISTFILES += \
WebEngineMP4Build_6.5.1.cmd \
WebEngineMP4Build_6.5.2.cmd \
qt.conf \
blue-folder.png \
Scratch.txt \
Expand All @@ -193,7 +167,8 @@ DISTFILES += \
new_message.png \
StyledButton.qml \
ReplyPopup.qml \
NewMessagePopup.qml
NewMessagePopup.qml \
win_deploy_6.5.2.cmd



Expand Down
181 changes: 167 additions & 14 deletions client_tools/lms/src/OPE_LMS/appmodule.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,45 @@
#include "appmodule.h"

AppModule::AppModule(QQmlApplicationEngine *parent) : QObject(parent)
AppModule::AppModule(QQmlApplicationEngine *parent, QString program_data_path) : QObject(parent)
{
HTTP_SERVER_PORT = 65525;
exit_early = false;
engine = parent;

//registerOPEAccessibilityComponents();

// Show SSL info
qDebug() << "SSL Library Info: " << QSslSocket::supportsSsl() << QSslSocket::sslLibraryBuildVersionString() << QSslSocket::sslLibraryVersionString();
// Relax ssl config as we will be running through test certs
QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration();
QList<QSslCertificate> cert_list = sslconf.caCertificates();
QList<QSslCertificate> cert_new = QSslCertificate::fromData("CaCertificates");
cert_list += cert_new;
sslconf.setCaCertificates(cert_list);
sslconf.setProtocol(QSsl::AnyProtocol);
sslconf.setPeerVerifyMode(QSslSocket::VerifyNone);
sslconf.setSslOption(QSsl::SslOptionDisableServerNameIndication,true);
QSslConfiguration::setDefaultConfiguration(sslconf);


nam_factory = new OPENetworkAccessManagerFactory;
if (program_data_path == "") {
// Get the standard program data folder to store things in.
program_data_path = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation).at(1); // grab 2nd item
// Remove app name (c:/programdata/ope/opelms -> c:/programdata/ope)
program_data_path = program_data_path.replace("/OPELMS", "");
}
this->data_path = program_data_path;

parent->setNetworkAccessManagerFactory(nam_factory);
parent->rootContext()->engine()->setNetworkAccessManagerFactory(nam_factory);

// Expose this object to the QML engine
parent->rootContext()->setContextProperty("mainWidget", this);

// Add our websocket transport so we can communicate with web pages in a webview
qmlRegisterType<CM_WebSocketTransport>("cm.WebSocketTransport", 1, 0, "WebSocketTransport");

//QObject *root = engine->rootObjects().first();
//root->setParent("networkAccess", parent->networkAccessManager());

Expand Down Expand Up @@ -37,17 +67,38 @@ AppModule::AppModule(QQmlApplicationEngine *parent) : QObject(parent)
_app_settings->sync();
//qDebug() << "App Settings: " << _app_settings->fileName();

// Prevent app from running twice
QString tmp_dir = this->appStudentDataFolder(); //QDir::tempPath();
qDebug() << tmp_dir;
if (tmp_dir.endsWith("/student_data") == true) {
// Should end with the current student (e.g. c:\programdata\ope\student_data\s77777) - if not, then not credentialed?
qDebug() << "Invalid student folder! Run credential and retry." << Qt::endl;
// QMessageBox msgbox;
// msgbox.setText("Invalid Student Folder!");
// msgbox.setInformativeText("Student username not detected - you must run the credential app to link this app to the student's Canvas account.");
// msgbox.setStandardButtons(QMessageBox::Ok);
// msgbox.exec();

QApplication::exit(-1);
return;
}

// Expose this object to the QML engine
//qmlRegisterType<EX_Canvas>("com.openprisoneducation.ope", 1, 0, "Canvas");
parent->rootContext()->setContextProperty("mainWidget", this);

// Add our websocket transport so we can communicate with web pages in a webview
qmlRegisterType<CM_WebSocketTransport>("cm.WebSocketTransport", 1, 0, "WebSocketTransport");
_lf = new QLockFile(tmp_dir + "/ope_lms.lock");
if (!_lf->tryLock(100))
{
qDebug() << "=====================================================\n" <<
"WARNING - App already running, exiting...\n" <<
"only one instance allowed to run. If this is an " <<
" error, remove the temp/ope_lms.lock file and try again" <<
"=====================================================\n";
out << "App already running..." << Qt::endl;
QApplication::exit(-1);
return;
}

// Figure out the database path
QDir d;
d.setPath(this->appDataFolder());
d.setPath(this->appStudentDataFolder());
d.mkpath(d.path());
QString db_file = d.path() + "/lms.db";

Expand Down Expand Up @@ -104,6 +155,10 @@ AppModule::~AppModule()
_app_settings->deleteLater();
}

if (_lf) {
_lf->unlock();
}

}

void AppModule::debugPrint(QString msg)
Expand Down Expand Up @@ -165,14 +220,36 @@ bool AppModule::desktopLaunch(QString url)
return ret;
}

QString AppModule::appDataFolder()
QString AppModule::appStudentDataFolder()
{

QString path = this->appDataFolder();
QString curr_student = this->get_current_student_user();

path += "/student_data";

if (curr_student == "") {
return path;
}

path += "/" + curr_student;

QDir d;
d.setPath(path);
if (!d.exists()) {
d.mkpath(d.path());
}

return path;

/*
// Find the appdata folder
// NOTE - if no user set in registry (not credentialed?), then grab dir for current user.
QString curr_student = this->get_current_student_user();
if (curr_student == "") {
// Return the standard path for the current logged in user.
QString p = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
//QString p = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QString p = this->data_path;
QDir d;
d.setPath(p);
d.mkpath(d.path());
Expand Down Expand Up @@ -206,6 +283,21 @@ QString AppModule::appDataFolder()
d.mkpath(d.path());
return app_data_path;
*/
}

QString AppModule::appDataFolder()
{
// Should return something like c:/programdata/ope

// Make sure folder exists
QDir d;
d.setPath(data_path);
if (!d.exists()) {
d.mkpath(d.path());
}

return this->data_path;
}

QString AppModule::dataFolder()
Expand All @@ -228,10 +320,12 @@ QString AppModule::dataFolder()
d.setPath(dataAbsPath);
#else
//d.setPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/content");
d.setPath(this->appDataFolder() + "/content");
d.setPath(this->appStudentDataFolder() + "/content");
#endif

d.mkpath(d.path());
if (!d.exists()) {
d.mkpath(d.path());
}

return d.path();
}
Expand All @@ -240,8 +334,10 @@ QString AppModule::fileCacheFolder()
{
QDir base_dir;
//base_dir.setPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/content/www_root/canvas_file_cache/");
base_dir.setPath(this->appDataFolder() + "/content/www_root/canvas_file_cache/");
base_dir.mkpath(base_dir.path());
base_dir.setPath(this->appStudentDataFolder() + "/content/www_root/canvas_file_cache/");
if (!base_dir.exists()) {
base_dir.mkpath(base_dir.path());
}
return base_dir.path();
}

Expand Down Expand Up @@ -684,3 +780,60 @@ QString AppModule::get_current_student_user()
return _app_settings->value("student/user_name", "").toString();
}

void AppModule::sendAccessibilityEvent(QQuickItem *item, QAccessible::Event event_reason)
{
QAccessibleEvent event(item, event_reason); // event(this, QAccessible::TextUpdated);

//event.accessibleInterface()-(QAccessible::TextUpdated);
//event.accessibleInterface()->setText(QAccessible::Description, QLatin1String("Hello WOrld!"));
QAccessible::updateAccessibility(&event);


// Find the root window so we can get the accessibility tree
// for (QObject *o: this->engine->rootObjects()) {
// qDebug() << "... > " << o;
// }
// QObject *rootObject = this->engine->rootObjects().first();
// QQuickItem *accessible_root = nullptr;
// //qDebug() << "RootObject: " << rootObject;
// if (rootObject->objectName() == "appPage") {
// // Root object IS the main window
// accessible_root = qobject_cast<QQuickItem*>(rootObject);
// qDebug() << "Casting: " << accessible_root;
// } else {
// accessible_root = rootObject->findChild<QQuickItem*>("appPage");
// }

// if (accessible_root == nullptr) {
// qDebug() << "No QML object found with object_name: appPage";
// return;
// }

// // Setup the update handler
// //QAccessible::installUpdateHandler(new OPECustomAccessibleItem(item));

// QAccessibleEvent event(this, QAccessible::Event::SoundPlayed);
// QObject *accessible_iface = dynamic_cast<QObject *>(QAccessible::queryAccessibleInterface(item));
// qDebug() << "Accessible Iface: " << accessible_iface;

// QAccessibleInterface *iface = event.accessibleInterface();
// qDebug() << "IFACe: " << iface;
// iface->setText(QAccessible::Text::Name, QStringLiteral("Hey WOrld"));
// QCoreApplication::sendEvent(accessible_iface, dynamic_cast<QEvent *>(&event));
// accessible_iface->deleteLater();

// // Send an accessibilty event from the QML system.
// QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item);
// //iface->item()

// iface->setText(QAccessible::Name, "TEst 1235");

// QString accessibleName = iface->text(QAccessible::Name);
// qDebug() << "A Name";
// //QAccessibleEvent event(iface, QAccessible::Focus);
// //qDebug() << "Accessibility Event " << event;
// QAccessibleEvent event(iface, QAccessible::NameChanged);
// QAccessible::updateAccessibility(&event.object());

}

Loading

0 comments on commit 1326d7b

Please sign in to comment.