You've already forked AstralRinth
forked from didirus/AstralRinth
Add fields to OAuth (#769)
* Add url and description fields to OAuthClient model * Add OAuth client icon editing and deleting endpoints * updated query data * fix missed queries * sqlx prep * update with tests builds
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "\n SELECT\n clients.id as \"id!\",\n clients.name as \"name!\",\n clients.icon_url as \"icon_url?\",\n clients.max_scopes as \"max_scopes!\",\n clients.secret_hash as \"secret_hash!\",\n clients.created as \"created!\",\n clients.created_by as \"created_by!\",\n uris.uri_ids as \"uri_ids?\",\n uris.uri_vals as \"uri_vals?\"\n FROM oauth_clients clients\n LEFT JOIN (\n SELECT client_id, array_agg(id) as uri_ids, array_agg(uri) as uri_vals\n FROM oauth_client_redirect_uris\n GROUP BY client_id\n ) uris ON clients.id = uris.client_id\n WHERE created_by = $1",
|
"query": "\n SELECT\n clients.id as \"id!\",\n clients.name as \"name!\",\n clients.icon_url as \"icon_url?\",\n clients.max_scopes as \"max_scopes!\",\n clients.secret_hash as \"secret_hash!\",\n clients.created as \"created!\",\n clients.created_by as \"created_by!\",\n clients.url as \"url?\",\n clients.description as \"description?\",\n uris.uri_ids as \"uri_ids?\",\n uris.uri_vals as \"uri_vals?\"\n FROM oauth_clients clients\n LEFT JOIN (\n SELECT client_id, array_agg(id) as uri_ids, array_agg(uri) as uri_vals\n FROM oauth_client_redirect_uris\n GROUP BY client_id\n ) uris ON clients.id = uris.client_id\n WHERE created_by = $1",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -40,11 +40,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 7,
|
||||||
|
"name": "url?",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "description?",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
"name": "uri_ids?",
|
"name": "uri_ids?",
|
||||||
"type_info": "Int8Array"
|
"type_info": "Int8Array"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 8,
|
"ordinal": 10,
|
||||||
"name": "uri_vals?",
|
"name": "uri_vals?",
|
||||||
"type_info": "TextArray"
|
"type_info": "TextArray"
|
||||||
}
|
}
|
||||||
@@ -62,9 +72,11 @@
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "8bfb350d4f539a110b05f42812ea2593a1556ef214f3bed519de6b6e21c7d477"
|
"hash": "467df7989a1f4f5f3bc3409a4060e89dcfdd5a5ab9c7a96dc4008e74e06be914"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "\n UPDATE oauth_clients\n SET name = $1, icon_url = $2, max_scopes = $3\n WHERE (id = $4)\n ",
|
"query": "\n UPDATE oauth_clients\n SET name = $1, icon_url = $2, max_scopes = $3, url = $4, description = $5\n WHERE (id = $6)\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
@@ -8,10 +8,12 @@
|
|||||||
"Text",
|
"Text",
|
||||||
"Text",
|
"Text",
|
||||||
"Int8",
|
"Int8",
|
||||||
|
"Text",
|
||||||
|
"Text",
|
||||||
"Int8"
|
"Int8"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "e8cc8895ebc8b1904a43e00f1e123f75ffdaebc76d67a5d35218fa9273d46d53"
|
"hash": "781f54f36b8713bd36f5f89c98f8c89e94cc7c54e0b7302c877586186bb128a2"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "\n SELECT\n clients.id as \"id!\",\n clients.name as \"name!\",\n clients.icon_url as \"icon_url?\",\n clients.max_scopes as \"max_scopes!\",\n clients.secret_hash as \"secret_hash!\",\n clients.created as \"created!\",\n clients.created_by as \"created_by!\",\n uris.uri_ids as \"uri_ids?\",\n uris.uri_vals as \"uri_vals?\"\n FROM oauth_clients clients\n LEFT JOIN (\n SELECT client_id, array_agg(id) as uri_ids, array_agg(uri) as uri_vals\n FROM oauth_client_redirect_uris\n GROUP BY client_id\n ) uris ON clients.id = uris.client_id\n WHERE clients.id = ANY($1::bigint[])",
|
"query": "\n SELECT\n clients.id as \"id!\",\n clients.name as \"name!\",\n clients.icon_url as \"icon_url?\",\n clients.max_scopes as \"max_scopes!\",\n clients.secret_hash as \"secret_hash!\",\n clients.created as \"created!\",\n clients.created_by as \"created_by!\",\n clients.url as \"url?\",\n clients.description as \"description?\",\n uris.uri_ids as \"uri_ids?\",\n uris.uri_vals as \"uri_vals?\"\n FROM oauth_clients clients\n LEFT JOIN (\n SELECT client_id, array_agg(id) as uri_ids, array_agg(uri) as uri_vals\n FROM oauth_client_redirect_uris\n GROUP BY client_id\n ) uris ON clients.id = uris.client_id\n WHERE clients.id = ANY($1::bigint[])",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -40,11 +40,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 7,
|
||||||
|
"name": "url?",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "description?",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
"name": "uri_ids?",
|
"name": "uri_ids?",
|
||||||
"type_info": "Int8Array"
|
"type_info": "Int8Array"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 8,
|
"ordinal": 10,
|
||||||
"name": "uri_vals?",
|
"name": "uri_vals?",
|
||||||
"type_info": "TextArray"
|
"type_info": "TextArray"
|
||||||
}
|
}
|
||||||
@@ -62,9 +72,11 @@
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "fdfb2433a8e407d42cec1791d67549ab5c23306758168af38f955c06d251b0b7"
|
"hash": "93190af0fcfe2e795ed6b90eece7c567b8724509d1fdbd5cc75f516c1811c9d3"
|
||||||
}
|
}
|
||||||
7
migrations/20231122230639_oauth_client_metadata.sql
Normal file
7
migrations/20231122230639_oauth_client_metadata.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
ALTER TABLE
|
||||||
|
oauth_clients
|
||||||
|
ADD
|
||||||
|
COLUMN url text NULL,
|
||||||
|
ADD
|
||||||
|
COLUMN description text NULL;
|
||||||
@@ -23,6 +23,8 @@ pub struct OAuthClient {
|
|||||||
pub redirect_uris: Vec<OAuthRedirectUri>,
|
pub redirect_uris: Vec<OAuthRedirectUri>,
|
||||||
pub created: DateTime<Utc>,
|
pub created: DateTime<Utc>,
|
||||||
pub created_by: UserId,
|
pub created_by: UserId,
|
||||||
|
pub url: Option<String>,
|
||||||
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClientQueryResult {
|
struct ClientQueryResult {
|
||||||
@@ -33,6 +35,8 @@ struct ClientQueryResult {
|
|||||||
secret_hash: String,
|
secret_hash: String,
|
||||||
created: DateTime<Utc>,
|
created: DateTime<Utc>,
|
||||||
created_by: i64,
|
created_by: i64,
|
||||||
|
url: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
uri_ids: Option<Vec<i64>>,
|
uri_ids: Option<Vec<i64>>,
|
||||||
uri_vals: Option<Vec<String>>,
|
uri_vals: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
@@ -53,6 +57,8 @@ macro_rules! select_clients_with_predicate {
|
|||||||
clients.secret_hash as "secret_hash!",
|
clients.secret_hash as "secret_hash!",
|
||||||
clients.created as "created!",
|
clients.created as "created!",
|
||||||
clients.created_by as "created_by!",
|
clients.created_by as "created_by!",
|
||||||
|
clients.url as "url?",
|
||||||
|
clients.description as "description?",
|
||||||
uris.uri_ids as "uri_ids?",
|
uris.uri_ids as "uri_ids?",
|
||||||
uris.uri_vals as "uri_vals?"
|
uris.uri_vals as "uri_vals?"
|
||||||
FROM oauth_clients clients
|
FROM oauth_clients clients
|
||||||
@@ -155,12 +161,14 @@ impl OAuthClient {
|
|||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE oauth_clients
|
UPDATE oauth_clients
|
||||||
SET name = $1, icon_url = $2, max_scopes = $3
|
SET name = $1, icon_url = $2, max_scopes = $3, url = $4, description = $5
|
||||||
WHERE (id = $4)
|
WHERE (id = $6)
|
||||||
",
|
",
|
||||||
self.name,
|
self.name,
|
||||||
self.icon_url,
|
self.icon_url,
|
||||||
self.max_scopes.to_postgres(),
|
self.max_scopes.to_postgres(),
|
||||||
|
self.url,
|
||||||
|
self.description,
|
||||||
self.id.0,
|
self.id.0,
|
||||||
)
|
)
|
||||||
.execute(exec)
|
.execute(exec)
|
||||||
@@ -240,6 +248,8 @@ impl From<ClientQueryResult> for OAuthClient {
|
|||||||
redirect_uris: redirects,
|
redirect_uris: redirects,
|
||||||
created: r.created,
|
created: r.created,
|
||||||
created_by: UserId(r.created_by),
|
created_by: UserId(r.created_by),
|
||||||
|
url: r.url,
|
||||||
|
description: r.description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ pub struct OAuthClient {
|
|||||||
|
|
||||||
// The user that created (and thus controls) this client
|
// The user that created (and thus controls) this client
|
||||||
pub created_by: UserId,
|
pub created_by: UserId,
|
||||||
|
|
||||||
|
// When this client was created
|
||||||
|
pub created: DateTime<Utc>,
|
||||||
|
|
||||||
|
// (optional) Metadata about the client
|
||||||
|
pub url: Option<String>,
|
||||||
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
@@ -88,6 +95,9 @@ impl From<DBOAuthClient> for OAuthClient {
|
|||||||
max_scopes: value.max_scopes,
|
max_scopes: value.max_scopes,
|
||||||
redirect_uris: value.redirect_uris.into_iter().map(|r| r.into()).collect(),
|
redirect_uris: value.redirect_uris.into_iter().map(|r| r.into()).collect(),
|
||||||
created_by: value.created_by.into(),
|
created_by: value.created_by.into(),
|
||||||
|
created: value.created,
|
||||||
|
url: value.url,
|
||||||
|
description: value.description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashSet, fmt::Display};
|
use std::{collections::HashSet, fmt::Display, sync::Arc};
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
delete, get, patch, post,
|
delete, get, patch, post,
|
||||||
@@ -16,7 +16,9 @@ use validator::Validate;
|
|||||||
use super::ApiError;
|
use super::ApiError;
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::checks::ValidateAllAuthorized,
|
auth::checks::ValidateAllAuthorized,
|
||||||
|
file_hosting::FileHost,
|
||||||
models::{ids::base62_impl::parse_base62, oauth_clients::DeleteOAuthClientQueryParam},
|
models::{ids::base62_impl::parse_base62, oauth_clients::DeleteOAuthClientQueryParam},
|
||||||
|
util::routes::read_from_payload,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::{checks::ValidateAuthorized, get_user_from_headers},
|
auth::{checks::ValidateAuthorized, get_user_from_headers},
|
||||||
@@ -50,6 +52,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||||||
.service(oauth_client_create)
|
.service(oauth_client_create)
|
||||||
.service(oauth_client_edit)
|
.service(oauth_client_edit)
|
||||||
.service(oauth_client_delete)
|
.service(oauth_client_delete)
|
||||||
|
.service(oauth_client_icon_edit)
|
||||||
|
.service(oauth_client_icon_delete)
|
||||||
.service(get_client)
|
.service(get_client)
|
||||||
.service(get_clients)
|
.service(get_clients)
|
||||||
.service(get_user_oauth_authorizations),
|
.service(get_user_oauth_authorizations),
|
||||||
@@ -145,6 +149,15 @@ pub struct NewOAuthApp {
|
|||||||
pub max_scopes: Scopes,
|
pub max_scopes: Scopes,
|
||||||
|
|
||||||
pub redirect_uris: Vec<String>,
|
pub redirect_uris: Vec<String>,
|
||||||
|
|
||||||
|
#[validate(
|
||||||
|
custom(function = "crate::util::validate::validate_url"),
|
||||||
|
length(max = 255)
|
||||||
|
)]
|
||||||
|
pub url: Option<String>,
|
||||||
|
|
||||||
|
#[validate(length(max = 255))]
|
||||||
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("app")]
|
#[post("app")]
|
||||||
@@ -187,6 +200,8 @@ pub async fn oauth_client_create<'a>(
|
|||||||
redirect_uris,
|
redirect_uris,
|
||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
created_by: current_user.id.into(),
|
created_by: current_user.id.into(),
|
||||||
|
url: new_oauth_app.url.clone(),
|
||||||
|
description: new_oauth_app.description.clone(),
|
||||||
secret_hash: client_secret_hash,
|
secret_hash: client_secret_hash,
|
||||||
};
|
};
|
||||||
client.clone().insert(&mut transaction).await?;
|
client.clone().insert(&mut transaction).await?;
|
||||||
@@ -248,6 +263,15 @@ pub struct OAuthClientEdit {
|
|||||||
|
|
||||||
#[validate(length(min = 1))]
|
#[validate(length(min = 1))]
|
||||||
pub redirect_uris: Option<Vec<String>>,
|
pub redirect_uris: Option<Vec<String>>,
|
||||||
|
|
||||||
|
#[validate(
|
||||||
|
custom(function = "crate::util::validate::validate_url"),
|
||||||
|
length(max = 255)
|
||||||
|
)]
|
||||||
|
pub url: Option<Option<String>>,
|
||||||
|
|
||||||
|
#[validate(length(max = 255))]
|
||||||
|
pub description: Option<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch("app/{id}")]
|
#[patch("app/{id}")]
|
||||||
@@ -289,6 +313,8 @@ pub async fn oauth_client_edit(
|
|||||||
icon_url,
|
icon_url,
|
||||||
max_scopes,
|
max_scopes,
|
||||||
redirect_uris,
|
redirect_uris,
|
||||||
|
url,
|
||||||
|
description,
|
||||||
} = client_updates.into_inner();
|
} = client_updates.into_inner();
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
updated_client.name = name;
|
updated_client.name = name;
|
||||||
@@ -302,6 +328,14 @@ pub async fn oauth_client_edit(
|
|||||||
updated_client.max_scopes = max_scopes;
|
updated_client.max_scopes = max_scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(url) = url {
|
||||||
|
updated_client.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(description) = description {
|
||||||
|
updated_client.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
let mut transaction = pool.begin().await?;
|
let mut transaction = pool.begin().await?;
|
||||||
updated_client
|
updated_client
|
||||||
.update_editable_fields(&mut *transaction)
|
.update_editable_fields(&mut *transaction)
|
||||||
@@ -319,6 +353,130 @@ pub async fn oauth_client_edit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Extension {
|
||||||
|
pub ext: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[patch("app/{id}/icon")]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub async fn oauth_client_icon_edit(
|
||||||
|
web::Query(ext): web::Query<Extension>,
|
||||||
|
req: HttpRequest,
|
||||||
|
client_id: web::Path<ApiOAuthClientId>,
|
||||||
|
pool: web::Data<PgPool>,
|
||||||
|
redis: web::Data<RedisPool>,
|
||||||
|
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
|
||||||
|
mut payload: web::Payload,
|
||||||
|
session_queue: web::Data<AuthQueue>,
|
||||||
|
) -> Result<HttpResponse, ApiError> {
|
||||||
|
if let Some(content_type) = crate::util::ext::get_image_content_type(&ext.ext) {
|
||||||
|
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||||
|
let user = get_user_from_headers(
|
||||||
|
&req,
|
||||||
|
&**pool,
|
||||||
|
&redis,
|
||||||
|
&session_queue,
|
||||||
|
Some(&[Scopes::SESSION_ACCESS]),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.1;
|
||||||
|
|
||||||
|
let client = OAuthClient::get((*client_id).into(), &**pool)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::InvalidInput("The specified client does not exist!".to_string())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
client.validate_authorized(Some(&user))?;
|
||||||
|
|
||||||
|
if let Some(ref icon) = client.icon_url {
|
||||||
|
let name = icon.split(&format!("{cdn_url}/")).nth(1);
|
||||||
|
|
||||||
|
if let Some(icon_path) = name {
|
||||||
|
file_host.delete_file_version("", icon_path).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes =
|
||||||
|
read_from_payload(&mut payload, 262144, "Icons must be smaller than 256KiB").await?;
|
||||||
|
let hash = sha1::Sha1::from(&bytes).hexdigest();
|
||||||
|
let upload_data = file_host
|
||||||
|
.upload_file(
|
||||||
|
content_type,
|
||||||
|
&format!("data/{}/{}.{}", client_id, hash, ext.ext),
|
||||||
|
bytes.freeze(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut transaction = pool.begin().await?;
|
||||||
|
|
||||||
|
let mut editable_client = client.clone();
|
||||||
|
editable_client.icon_url = Some(format!("{}/{}", cdn_url, upload_data.file_name));
|
||||||
|
|
||||||
|
editable_client
|
||||||
|
.update_editable_fields(&mut *transaction)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
transaction.commit().await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::NoContent().body(""))
|
||||||
|
} else {
|
||||||
|
Err(ApiError::InvalidInput(format!(
|
||||||
|
"Invalid format for project icon: {}",
|
||||||
|
ext.ext
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[delete("app/{id}/icon")]
|
||||||
|
pub async fn oauth_client_icon_delete(
|
||||||
|
req: HttpRequest,
|
||||||
|
client_id: web::Path<ApiOAuthClientId>,
|
||||||
|
pool: web::Data<PgPool>,
|
||||||
|
redis: web::Data<RedisPool>,
|
||||||
|
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
|
||||||
|
session_queue: web::Data<AuthQueue>,
|
||||||
|
) -> Result<HttpResponse, ApiError> {
|
||||||
|
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||||
|
let user = get_user_from_headers(
|
||||||
|
&req,
|
||||||
|
&**pool,
|
||||||
|
&redis,
|
||||||
|
&session_queue,
|
||||||
|
Some(&[Scopes::SESSION_ACCESS]),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.1;
|
||||||
|
|
||||||
|
let client = OAuthClient::get((*client_id).into(), &**pool)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::InvalidInput("The specified client does not exist!".to_string())
|
||||||
|
})?;
|
||||||
|
client.validate_authorized(Some(&user))?;
|
||||||
|
|
||||||
|
if let Some(ref icon) = client.icon_url {
|
||||||
|
let name = icon.split(&format!("{cdn_url}/")).nth(1);
|
||||||
|
|
||||||
|
if let Some(icon_path) = name {
|
||||||
|
file_host.delete_file_version("", icon_path).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut transaction = pool.begin().await?;
|
||||||
|
|
||||||
|
let mut editable_client = client.clone();
|
||||||
|
editable_client.icon_url = None;
|
||||||
|
|
||||||
|
editable_client
|
||||||
|
.update_editable_fields(&mut *transaction)
|
||||||
|
.await?;
|
||||||
|
transaction.commit().await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::NoContent().body(""))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("authorizations")]
|
#[get("authorizations")]
|
||||||
pub async fn get_user_oauth_authorizations(
|
pub async fn get_user_oauth_authorizations(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ async fn can_create_edit_get_oauth_client() {
|
|||||||
let client_id = get_json_val_str(creation_result.client.id);
|
let client_id = get_json_val_str(creation_result.client.id);
|
||||||
|
|
||||||
let icon_url = Some("https://modrinth.com/icon".to_string());
|
let icon_url = Some("https://modrinth.com/icon".to_string());
|
||||||
|
let url = Some("https://modrinth.com".to_string());
|
||||||
|
let description = Some("test description".to_string());
|
||||||
let edited_redirect_uris = vec![
|
let edited_redirect_uris = vec![
|
||||||
redirect_uris[0].clone(),
|
redirect_uris[0].clone(),
|
||||||
"https://modrinth.com/b".to_string(),
|
"https://modrinth.com/b".to_string(),
|
||||||
@@ -50,6 +52,8 @@ async fn can_create_edit_get_oauth_client() {
|
|||||||
icon_url: Some(icon_url.clone()),
|
icon_url: Some(icon_url.clone()),
|
||||||
max_scopes: None,
|
max_scopes: None,
|
||||||
redirect_uris: Some(edited_redirect_uris.clone()),
|
redirect_uris: Some(edited_redirect_uris.clone()),
|
||||||
|
url: Some(url.clone()),
|
||||||
|
description: Some(description.clone()),
|
||||||
};
|
};
|
||||||
let resp = env
|
let resp = env
|
||||||
.api
|
.api
|
||||||
@@ -63,6 +67,8 @@ async fn can_create_edit_get_oauth_client() {
|
|||||||
.await;
|
.await;
|
||||||
assert_eq!(1, clients.len());
|
assert_eq!(1, clients.len());
|
||||||
assert_eq!(icon_url, clients[0].icon_url);
|
assert_eq!(icon_url, clients[0].icon_url);
|
||||||
|
assert_eq!(url, clients[0].url);
|
||||||
|
assert_eq!(description, clients[0].description);
|
||||||
assert_eq!(client_name, clients[0].name);
|
assert_eq!(client_name, clients[0].name);
|
||||||
assert_eq!(2, clients[0].redirect_uris.len());
|
assert_eq!(2, clients[0].redirect_uris.len());
|
||||||
assert_eq!(edited_redirect_uris[0], clients[0].redirect_uris[0].uri);
|
assert_eq!(edited_redirect_uris[0], clients[0].redirect_uris[0].uri);
|
||||||
|
|||||||
Reference in New Issue
Block a user