diff --git a/crates/core/src/database/user/auth_token.rs b/crates/core/src/database/user/auth_token.rs index 6cd7c5e9..03f5e2a9 100644 --- a/crates/core/src/database/user/auth_token.rs +++ b/crates/core/src/database/user/auth_token.rs @@ -95,6 +95,26 @@ impl AuthToken { }; Ok(actions.contains(&repository_action)) } + pub async fn get_by_id_and_user_id( + id: i32, + user_id: i32, + database: &PgPool, + ) -> sqlx::Result> { + let token = + sqlx::query_as(r#"SELECT * FROM user_auth_tokens WHERE id = $1 AND user_id = $2"#) + .bind(id) + .bind(user_id) + .fetch_optional(database) + .await?; + Ok(token) + } + pub async fn delete(&self, database: &PgPool) -> sqlx::Result<()> { + sqlx::query(r#"DELETE FROM user_auth_tokens WHERE id = $1"#) + .bind(self.id) + .execute(database) + .await?; + Ok(()) + } } #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct NewAuthToken { diff --git a/nitro_repo/src/app/api/user/tokens.rs b/nitro_repo/src/app/api/user/tokens.rs index 5af593c4..d2236e16 100644 --- a/nitro_repo/src/app/api/user/tokens.rs +++ b/nitro_repo/src/app/api/user/tokens.rs @@ -1,13 +1,17 @@ use axum::{ + body::Body, extract::{Path, State}, response::Response, - routing::{get, post}, + routing::{delete, get, post}, Json, }; use axum_extra::{headers::UserAgent, TypedHeader}; use http::StatusCode; use nr_core::{ - database::user::{auth_token::NewAuthToken, UserType}, + database::user::{ + auth_token::{AuthToken, NewAuthToken}, + UserType, + }, user::{permissions::RepositoryActions, scopes::NRScope, token::AuthTokenFullResponse}, }; use serde::{Deserialize, Serialize}; @@ -27,6 +31,7 @@ pub fn token_routes() -> axum::Router { .route("/create", post(create)) .route("/list", get(list)) .route("/get/:id", get(get_token)) + .route("/delete/:id", delete(delete_token)) } #[derive(Debug, Serialize, Deserialize, ToSchema)] @@ -129,3 +134,29 @@ async fn get_token( .status(StatusCode::OK) .json_body(&tokens) } +#[utoipa::path( + delete, + path = "/token/delete/{id}", + responses( + (status = 200, description = "Token Deleted"), + ), +)] +#[instrument] +async fn delete_token( + auth: OnlySessionAllowedAuthentication, + Path(id): Path, + State(site): State, +) -> Result { + let Some(token) = AuthToken::get_by_id_and_user_id(id, auth.get_id(), site.as_ref()).await? + else { + return Ok(Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap()); + }; + token.delete(site.as_ref()).await?; + Ok(Response::builder() + .status(StatusCode::NO_CONTENT) + .body(Body::empty()) + .unwrap()) +} diff --git a/nitro_repo/src/repository/npm/login/couch_db.rs b/nitro_repo/src/repository/npm/login/couch_db.rs index 01f54b16..4396347d 100644 --- a/nitro_repo/src/repository/npm/login/couch_db.rs +++ b/nitro_repo/src/repository/npm/login/couch_db.rs @@ -1,6 +1,5 @@ use std::fmt::Debug; -use chrono::{DateTime, FixedOffset}; use derive_more::derive::From; use nr_core::{ database::user::auth_token::NewRepositoryToken, user::permissions::RepositoryActions, diff --git a/site/src/components/nav/sideNav/SideNav.vue b/site/src/components/nav/sideNav/SideNav.vue index 10022772..7603d290 100644 --- a/site/src/components/nav/sideNav/SideNav.vue +++ b/site/src/components/nav/sideNav/SideNav.vue @@ -16,28 +16,7 @@ nav { flex-direction: column; gap: 0.5rem; } -.navLink { - text-decoration: none; - color: $text; - font-weight: bold; - padding: 0.5rem; - // Align text vertically - display: flex; - align-items: center; - gap: 0.5rem; - // Box - border-radius: 0.5rem; - &:hover { - background-color: $primary-70; - transition: background-color 0.3s ease; - } -} -.navLink[data-active='true'] { - background-color: $primary-70; - &:hover { - cursor: default; - } -} + #logoAndHome { img { width: 2rem; diff --git a/site/src/components/repository/RepositoryToActionList.vue b/site/src/components/repository/RepositoryToActionList.vue index 955165c9..005bab09 100644 --- a/site/src/components/repository/RepositoryToActionList.vue +++ b/site/src/components/repository/RepositoryToActionList.vue @@ -19,33 +19,26 @@
-
- +
- +
- +
- +
-
@@ -69,34 +62,31 @@ function getRepositoryName(repositoryId: string) { const repositoryEntries = defineModel>({ required: true }) -const newRepositoryScopeEntry = ref({ +const newEntry = ref({ repositoryId: '', actions: new RepositoryActionsType([]) }) const isNewEntryValid = computed(() => { - if ( - !newRepositoryScopeEntry.value.repositoryId || - newRepositoryScopeEntry.value.repositoryId == '' - ) { + if (!newEntry.value.repositoryId || newEntry.value.repositoryId == '') { return false } - if (newRepositoryScopeEntry.value.actions.asArray().length === 0) { + if (newEntry.value.actions.asArray().length === 0) { return false } return true }) -function addRepositoryScopeEntry() { +function addEntry() { for (const repository of repositoryEntries.value) { - if (repository.repositoryId === newRepositoryScopeEntry.value.repositoryId) { - repository.actions = newRepositoryScopeEntry.value.actions + if (repository.repositoryId === newEntry.value.repositoryId) { + repository.actions = newEntry.value.actions notify({ type: 'success', title: 'Repository Already Exists', text: 'Values have been updated.' }) - newRepositoryScopeEntry.value = { + newEntry.value = { repositoryId: '', actions: new RepositoryActionsType([]) } @@ -104,16 +94,16 @@ function addRepositoryScopeEntry() { } } repositoryEntries.value.push({ - repositoryId: newRepositoryScopeEntry.value.repositoryId, - actions: newRepositoryScopeEntry.value.actions + repositoryId: newEntry.value.repositoryId, + actions: newEntry.value.actions }) - newRepositoryScopeEntry.value = { + newEntry.value = { repositoryId: '', actions: new RepositoryActionsType([]) } } -function removeRepositoryScopeEntry(id: string) { +function removeEntry(id: string) { repositoryEntries.value = repositoryEntries.value.filter((entry) => entry.repositoryId !== id) } diff --git a/site/src/router/index.ts b/site/src/router/index.ts index aa336946..f24ebf9e 100644 --- a/site/src/router/index.ts +++ b/site/src/router/index.ts @@ -16,6 +16,7 @@ declare module 'vue-router' { requiresRepositoryManager?: boolean requiresUserManager?: boolean sideBar?: Component + tag?: string } } const router = createRouter({ diff --git a/site/src/views/profile/ProfileTokens.vue b/site/src/views/profile/ProfileTokens.vue index 5ee6f8ad..b7432ce8 100644 --- a/site/src/views/profile/ProfileTokens.vue +++ b/site/src/views/profile/ProfileTokens.vue @@ -9,7 +9,7 @@ :data-expanded="expandedToken == token.token.id" @click="tokenClicked(token.token.id)">
- +
-
-

Repository Scopes

-
-
-

Scopes

-
- + Delete
@@ -31,6 +25,7 @@