Files
AstralRinth/apps/labrinth/src/models/v3/shared_instances.rs
Josiah Glosson cc34e69524 Initial shared instances backend (#3800)
* Create base shared instance migration and initial routes

* Fix build

* Add version uploads

* Add permissions field for shared instance users

* Actually use permissions field

* Add "public" flag to shared instances that allow GETing them without authorization

* Add the ability to get and list shared instance versions

* Add the ability to delete shared instance versions

* Fix build after merge

* Secured file hosting (#3784)

* Remove Backblaze-specific file-hosting backend

* Added S3_USES_PATH_STYLE_BUCKETS

* Remove unused file_id parameter from delete_file_version

* Add support for separate public and private buckets in labrinth::file_hosting

* Rename delete_file_version to delete_file

* Add (untested) get_url_for_private_file

* Remove url field from shared instance routes

* Remove url field from shared instance routes

* Use private bucket for shared instance versions

* Make S3 environment variables fully separate between public and private buckets

* Change file host expiry for shared instances to 180 seconds

* Fix lint

* Merge shared instance migrations into a single migration

* Replace shared instance owners with Ghost instead of deleting the instance
2025-06-19 19:46:12 +00:00

90 lines
2.6 KiB
Rust

use crate::bitflags_serde_impl;
use crate::database::models::shared_instance_item::{
DBSharedInstance, DBSharedInstanceUser, DBSharedInstanceVersion,
};
use crate::models::ids::{SharedInstanceId, SharedInstanceVersionId};
use ariadne::ids::UserId;
use bitflags::bitflags;
use chrono::{DateTime, Utc};
use hex::ToHex;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SharedInstance {
pub id: SharedInstanceId,
pub title: String,
pub owner: UserId,
pub public: bool,
pub current_version: Option<SharedInstanceVersion>,
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_users: Option<Vec<SharedInstanceUser>>,
}
impl SharedInstance {
pub fn from_db(
instance: DBSharedInstance,
users: Option<Vec<DBSharedInstanceUser>>,
current_version: Option<DBSharedInstanceVersion>,
) -> Self {
SharedInstance {
id: instance.id.into(),
title: instance.title,
owner: instance.owner_id.into(),
public: instance.public,
current_version: current_version.map(Into::into),
additional_users: users
.map(|x| x.into_iter().map(Into::into).collect()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SharedInstanceVersion {
pub id: SharedInstanceVersionId,
pub shared_instance: SharedInstanceId,
pub size: u64,
pub sha512: String,
pub created: DateTime<Utc>,
}
impl From<DBSharedInstanceVersion> for SharedInstanceVersion {
fn from(value: DBSharedInstanceVersion) -> Self {
let version_id = value.id.into();
let shared_instance_id = value.shared_instance_id.into();
SharedInstanceVersion {
id: version_id,
shared_instance: shared_instance_id,
size: value.size,
sha512: value.sha512.encode_hex(),
created: value.created,
}
}
}
bitflags! {
#[derive(Copy, Clone, Debug)]
pub struct SharedInstanceUserPermissions: u64 {
const EDIT = 1 << 0;
const DELETE = 1 << 1;
const UPLOAD_VERSION = 1 << 2;
const DELETE_VERSION = 1 << 3;
}
}
bitflags_serde_impl!(SharedInstanceUserPermissions, u64);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SharedInstanceUser {
pub user: UserId,
pub permissions: SharedInstanceUserPermissions,
}
impl From<DBSharedInstanceUser> for SharedInstanceUser {
fn from(user: DBSharedInstanceUser) -> Self {
SharedInstanceUser {
user: user.user_id.into(),
permissions: user.permissions,
}
}
}