All checks were successful
CI / container-job (push) Successful in 41s
- adonisrc.ts: Load official drive_provider and unload custom driver_provider. - packages.json: Add @headlessui/vue dependency for tab components. - AvatarController.ts: Rewrite avatar generation logic to always return the same avatar per user. - auth/UserController.ts: Add profile and profileUpdate methods to support user profile editing. - Submitter/datasetController.ts & app/models/file.ts: Adapt code to use the official drive_provider. - app/models/user.ts: Introduce “isAdmin” getter. - config/drive.ts: Create new configuration for the official drive_provider. - providers/vinejs_provider.ts: Adapt allowedExtensions control to use provided options or database enabled extensions. - resource/js/app.ts: Load default Head and Link components. - resources/js/menu.ts: Add settings-profile.edit menu point. - resources/js/Components/action-message.vue: Add new component for improved user feedback after form submissions. - New avatar-input.vue component: Enable profile picture selection. - Components/CardBox.vue: Alter layout to optionally show HeaderIcon in title bar. - FormControl.vue: Define a readonly prop for textareas. - Improve overall UI with updates to NavBar.vue, UserAvatar.vue, UserAvatarCurrentUser.vue, and add v-model support to password-meter.vue. - Remove profile editing logic from AccountInfo.vue and introduce new profile components (show.vue, update-password-form.vue, update-profile-information.vue). - app.edge: Modify page (add @inertiaHead tag) for better meta management. - routes.ts: Add new routes for editing user profiles. - General npm updates.
160 lines
5.7 KiB
TypeScript
160 lines
5.7 KiB
TypeScript
import fsExtra from 'fs-extra';
|
|
// import { RouterContract } from '@ioc:Adonis/Core/Route';
|
|
// import { Visibility, DriveFileStats, ContentHeaders, LocalDriverConfig, LocalDriverContract, DirectoryListingContract, LocalDriveListItem } from '@ioc:Adonis/Core/Drive';
|
|
|
|
import {
|
|
CannotGetMetaDataException,
|
|
CannotDeleteFileException,
|
|
CannotListDirectoryException,
|
|
CannotMoveFileException,
|
|
CannotGenerateUrlException,
|
|
} from '../exceptions/index.js';
|
|
import PathPrefixer from '../path_prefixer/index.js';
|
|
import { LocalDriverContract, LocalDriverConfig, DriverContract, DriveListItem } from '../src/types/drive.js';
|
|
import { AsyncIterableArray } from '../src/iterable_array.js';
|
|
import router from '@adonisjs/core/services/router'
|
|
/**
|
|
* Local driver interacts with the local file system
|
|
*/
|
|
export class LocalDriver implements LocalDriverContract {
|
|
private diskName: string;
|
|
private routeName: string;
|
|
private config;
|
|
// private router;
|
|
// private routeName;
|
|
|
|
/**
|
|
* Reference to the underlying adapter. Which is
|
|
* fs-extra
|
|
*/
|
|
adapter: typeof fsExtra;
|
|
|
|
/**
|
|
* Name of the driver
|
|
*/
|
|
name: 'local';
|
|
/**
|
|
* Path prefixer used for prefixing paths with disk root
|
|
*/
|
|
private prefixer;
|
|
|
|
// constructor(diskName: string, config: LocalDriverConfig, router: RouterContract);
|
|
constructor(diskName: string, config: LocalDriverConfig) {
|
|
this.diskName = diskName;
|
|
this.config = config;
|
|
// this.router = router;
|
|
this.routeName = ""; //LocalFileServer_1.LocalFileServer.makeRouteName(this.diskName);
|
|
/**
|
|
* Reference to the underlying adapter. Which is
|
|
* fs-extra
|
|
*/
|
|
this.adapter = fsExtra;
|
|
/**
|
|
* Name of the driver
|
|
*/
|
|
this.name = 'local';
|
|
/**
|
|
* Path prefixer used for prefixing paths with disk root
|
|
*/
|
|
this.prefixer = PathPrefixer.fromPath(this.config.root); //root: '/storage/app/public',
|
|
}
|
|
|
|
/**
|
|
* Returns a URL for a given location path
|
|
*/
|
|
public async getUrl(location: string) {
|
|
if (!this.config.serveFiles) {
|
|
throw CannotGenerateUrlException.invoke(location, this.diskName);
|
|
}
|
|
return router.makeUrl(this.routeName);
|
|
}
|
|
|
|
/**
|
|
* A boolean to find if the location path exists or not
|
|
*/
|
|
public async exists(location: string): Promise<boolean> {
|
|
try {
|
|
let path_temp = this.makePath(location); //'/storage/app/files/421'
|
|
return await this.adapter.pathExists(path_temp);
|
|
} catch (error) {
|
|
throw CannotGetMetaDataException.invoke(location, 'exists', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make absolute path to a given location
|
|
*/
|
|
public makePath(location: string): string {
|
|
return this.prefixer.prefixPath(location);
|
|
}
|
|
|
|
/**
|
|
* Remove a given location path
|
|
*/
|
|
// delete(location: string, ...args: any[]): Promise<void>;
|
|
public async delete(location: string): Promise<void> {
|
|
try {
|
|
await this.adapter.remove(this.makePath(location));
|
|
} catch (error) {
|
|
throw CannotDeleteFileException.invoke(location, error);
|
|
}
|
|
}
|
|
|
|
public async move(source: string, destination: string): Promise<void> {
|
|
try {
|
|
let sourcePath = this.makePath(source); //'/storage/app/public/tmp/rtwgliatumwwpd4vpayo4ymg'
|
|
let destinationPath = this.makePath(destination);
|
|
await this.adapter.move(sourcePath, destinationPath, {
|
|
overwrite: true,
|
|
});
|
|
await this.adapter.move(this.makePath(source), this.makePath(destination), {
|
|
overwrite:true
|
|
});
|
|
} catch (error) {
|
|
throw CannotMoveFileException.invoke(source, destination, error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a listing directory iterator for given location.
|
|
*/
|
|
public list(location: string): AsyncIterableArray<DriverContract, DriveListItem<any>> {
|
|
// public async list(location: string): Promise<DirectoryListing<DriverContract, DriveListItem<any>>> {
|
|
const fullPath = this.makePath(location); //'/storage/app/public/files/307'
|
|
|
|
// let dirListing: DirectoryListing<DriverContract, DriveListItem<any>> = new DirectoryListing(this, () => this.getListing(fullPath, location));
|
|
let dirListing: AsyncIterableArray<DriverContract, DriveListItem<any>> = new AsyncIterableArray(this, () =>
|
|
this.getListing(fullPath, location),
|
|
);
|
|
return dirListing;
|
|
// let listing: DriveListItem<fsExtra.Dirent>[] = await this.getListing(fullPath, location);
|
|
// let test = new DirectoryListing(this, listing);
|
|
// return test;
|
|
}
|
|
|
|
// Example usage
|
|
// private async *generateNumbers(): AsyncGenerator<number, void, unknown> {
|
|
// yield 1;
|
|
// yield 2;
|
|
// yield 3;
|
|
// }
|
|
|
|
private async *getListing(fullPath: string, location: string): AsyncGenerator<DriveListItem<fsExtra.Dirent>, void, unknown> {
|
|
// private async getListing(fullPath: string, location: string): Promise<DriveListItem<fsExtra.Dirent>[]> {
|
|
try {
|
|
const dir = await this.adapter.opendir(fullPath);
|
|
const prefixer = this.prefixer.withStrippedPrefix(fullPath);
|
|
// const listing: DriveListItem<fsExtra.Dirent>[] = new Array();
|
|
for await (const dirent of dir) {
|
|
yield {
|
|
location: prefixer.prefixPath(dirent.name),
|
|
isFile: dirent.isFile(),
|
|
original: dirent,
|
|
};
|
|
}
|
|
// return listing;
|
|
} catch (error) {
|
|
throw CannotListDirectoryException.invoke(location, error);
|
|
}
|
|
}
|
|
}
|