added userDtos
This commit is contained in:
6
.env
6
.env
@@ -2,3 +2,9 @@
|
|||||||
sike you thought I was like that
|
sike you thought I was like that
|
||||||
|
|
||||||
hehehehee (urp so full)
|
hehehehee (urp so full)
|
||||||
|
|
||||||
|
# TODO: should have basic public-safe environment variables here
|
||||||
|
# then secret environment variables can be added via secrets in the ci script like so:
|
||||||
|
# job: inject-seccrets $ echo API_KEY={{ secrets.API_KEY }} >> .env
|
||||||
|
# then they dont have to be inserted by the docker container ( messy)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,23 @@ public class UsersController : ControllerBase {
|
|||||||
[Authorize(Policy = "RequireAdmin")]
|
[Authorize(Policy = "RequireAdmin")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<List<User>>> getUsers() {
|
public async Task<ActionResult<List<User>>> getUsers() {
|
||||||
return Ok(await service_.GetAll());
|
List<User> rawArray = await service_.GetAll();
|
||||||
|
|
||||||
|
List<UserDto> dtoArray = new List<UserDto>();
|
||||||
|
|
||||||
|
foreach(User user in rawArray) {
|
||||||
|
// TODO: can you operator overload a cast? if so cast<UserDto>(UserDto) would go hard
|
||||||
|
// if not then just a new custom cast function that returns a dto type will do
|
||||||
|
UserDto newDto = new UserDto{
|
||||||
|
CreatedAt = user.CreatedAt,
|
||||||
|
Email = user.Email,
|
||||||
|
Id = user.Id,
|
||||||
|
UserName = user.UserName
|
||||||
|
};
|
||||||
|
dtoArray.Add(newDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(dtoArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = "RequireAdmin")]
|
[Authorize(Policy = "RequireAdmin")]
|
||||||
@@ -34,7 +50,14 @@ public class UsersController : ControllerBase {
|
|||||||
|
|
||||||
if (user == null) return NotFound();
|
if (user == null) return NotFound();
|
||||||
|
|
||||||
return Ok(user);
|
UserDto newDto = new UserDto{
|
||||||
|
CreatedAt = user.CreatedAt,
|
||||||
|
Email = user.Email,
|
||||||
|
Id = user.Id,
|
||||||
|
UserName = user.UserName
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(newDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = "RequireSuperuser")]
|
[Authorize(Policy = "RequireSuperuser")]
|
||||||
|
|||||||
@@ -46,3 +46,12 @@ public class LoginDto {
|
|||||||
public string Password { get; set; } = "";
|
public string Password { get; set; } = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UserDto {
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // gets compressed to a string
|
||||||
|
public string? Email { get; set; } = "";
|
||||||
|
public string Id { get; set; } = "";
|
||||||
|
public string? UserName { get; set; } = "";
|
||||||
|
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// handles user registration, user logins, tokens, password reset, etc.
|
// handles user registration, user logins, tokens, password reset, etc.
|
||||||
|
|
||||||
import { api, authStorage } from "./axios.ts"
|
import { api, authStorage } from "./axios.ts"
|
||||||
import type { User, RegisterDto, LoginDto } from "../models/User.ts";
|
import type { UserDto, RegisterDto, LoginDto } from "../models/User.ts";
|
||||||
|
|
||||||
const API_URL: string = "/auth";
|
const API_URL: string = "/auth";
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
import api from "./axios.ts"
|
import api from "./axios.ts"
|
||||||
import type { User } from "../models/User.ts";
|
import type { UserDto } from "../models/User.ts";
|
||||||
|
|
||||||
const API_URL: string = "/users";
|
const API_URL: string = "/users";
|
||||||
|
|
||||||
export const getUsers = () => api.get<User[]>(`${API_URL}`);
|
export const getUsers = () => api.get<UserDto[]>(`${API_URL}`);
|
||||||
|
|
||||||
export const getUser = (id: number) => api.get<User>(`${API_URL}/${id}`);
|
export const getUser = (id: string) => api.get<UserDto>(`${API_URL}/${id}`);
|
||||||
|
|
||||||
export const deleteUser = (id: number) => api.delete<User>(`${API_URL}/${id}`);
|
export const deleteUser = (id: string) => api.delete<UserDto>(`${API_URL}/${id}`);
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
// models are the data objects stored in the database. models defined here must match models defined in api/models
|
// models are the data objects stored in the database. models defined here must match models defined in api/models
|
||||||
// dtos here must match the the dtos in api/src/Modelts/Dto.cs in name (case insensitive) (types are intermediately serialized to strings)
|
// dtos here must match the the dtos in api/src/Modelts/Dto.cs in name (case insensitive) (types are intermediately serialized to strings)
|
||||||
|
|
||||||
export interface User {
|
export interface UserDto {
|
||||||
id: number;
|
createdAt: string;
|
||||||
username: string;
|
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
id: string;
|
||||||
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RegisterDto {
|
export interface RegisterDto {
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
<!-- pages/views in vue are basically root-level full-page components -->
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
import { useRoute, useRouter } from "vue-router";
|
|
||||||
|
|
||||||
import { useItemsStore } from "../stores/ItemsStore.ts";
|
|
||||||
import type { Item } from "../models/Item.ts";
|
|
||||||
|
|
||||||
const store = useItemsStore();
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const item = ref<Item>({
|
|
||||||
id: 0,
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
createdAt: "",
|
|
||||||
lastEditedAt: ""
|
|
||||||
});
|
|
||||||
|
|
||||||
const id: string | undefined = route.params.id as string | undefined
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if(id) {
|
|
||||||
const existing = store.items.find(i => i.id == Number(id));
|
|
||||||
if (existing) item.value = { ...existing };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function save(): Promise<void> {
|
|
||||||
if(id) {
|
|
||||||
await store.updateItem(Number(id), item.value);
|
|
||||||
} else {
|
|
||||||
await store.addItem(item.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
router.push("/items"); // redirect
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h2>{{ id ? "Edit Item" : "Create Item" }}</h2> <!-- omg I love ternary operator :D -->
|
|
||||||
|
|
||||||
<form @submit.prevent="save">
|
|
||||||
<input v-model="item.name" placeholder="Name" />
|
|
||||||
<input v-model="item.description" placeholder="Name" />
|
|
||||||
<button type="submit">Save</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import { onMounted } from "vue"
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { useUsersStore } from "../stores/UsersStore.ts"
|
||||||
|
import * as authApi from "../api/AuthApi";
|
||||||
|
|
||||||
|
const store = useUsersStore()
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
store.fetchUsers()
|
||||||
|
})
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
authApi.logout();
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Users</h1>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr v-for="user in store.users" :key="user.id">
|
||||||
|
<td>{{ user.username }}</td>
|
||||||
|
<td>
|
||||||
|
<button @click="store.removeUser(user.id)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button @click="logout()">Logout</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -10,10 +10,16 @@
|
|||||||
<h3>yeah im so cool rn</h3>
|
<h3>yeah im so cool rn</h3>
|
||||||
<h1>imagining what I could do with themes :o</h1>
|
<h1>imagining what I could do with themes :o</h1>
|
||||||
|
|
||||||
|
<h3>TODO: if(logged in) show this stuff; else dont.</h3>
|
||||||
|
|
||||||
<router-link to="/items" custom v-slot="{ navigate }">
|
<router-link to="/items" custom v-slot="{ navigate }">
|
||||||
<button @click="navigate" role="link">Items</button>
|
<button @click="navigate" role="link">Items</button>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
|
<router-link to="/users" custom v-slot="{ navigate }">
|
||||||
|
<button @click="navigate" role="link">Users</button>
|
||||||
|
</router-link>
|
||||||
|
|
||||||
<router-link to="/register" custom v-slot="{ navigate }"> <!-- TODO: only if token == invalid -->
|
<router-link to="/register" custom v-slot="{ navigate }"> <!-- TODO: only if token == invalid -->
|
||||||
<button @click="navigate" role="link">Register</button>
|
<button @click="navigate" role="link">Register</button>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import LoginForm from "../pages/LoginForm.vue";
|
|||||||
import RegisterForm from "../pages/RegisterForm.vue";
|
import RegisterForm from "../pages/RegisterForm.vue";
|
||||||
import ItemsList from "../pages/ItemsList.vue";
|
import ItemsList from "../pages/ItemsList.vue";
|
||||||
import ItemForm from "../pages/ItemForm.vue";
|
import ItemForm from "../pages/ItemForm.vue";
|
||||||
|
import UsersList from "../pages/UsersList.vue";
|
||||||
import index from "../pages/index.vue";
|
import index from "../pages/index.vue";
|
||||||
|
|
||||||
import { authStorage } from "../api/axios.ts"
|
import { authStorage } from "../api/axios.ts"
|
||||||
@@ -18,7 +19,7 @@ const routes = [
|
|||||||
{ path: "/items", component: ItemsList, meta: { requiresAuth: true } },
|
{ path: "/items", component: ItemsList, meta: { requiresAuth: true } },
|
||||||
{ path: "/item/new", component: ItemForm, meta: { requiresAuth: true } },
|
{ path: "/item/new", component: ItemForm, meta: { requiresAuth: true } },
|
||||||
{ path: "/item/:id", component: ItemForm, meta: { requiresAuth: true } },
|
{ path: "/item/:id", component: ItemForm, meta: { requiresAuth: true } },
|
||||||
{ path: "/users", component: ItemsList, meta: { requiresAuth: true } }
|
{ path: "/users", component: UsersList, meta: { requiresAuth: true } }
|
||||||
]; // I really like this
|
]; // I really like this
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import type { User } from "../models/User.ts";
|
import type { UserDto } from "../models/User.ts";
|
||||||
import * as usersApi from "../api/UsersApi";
|
import * as usersApi from "../api/UsersApi";
|
||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
users: User[];
|
users: UserDto[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export const useUsersStore = defineStore("users", {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeUser(id: number) {
|
async removeUser(id: string) {
|
||||||
await usersApi.deleteUser(id);
|
await usersApi.deleteUser(id);
|
||||||
this.users = this.users.filter(i => i.id !== id);
|
this.users = this.users.filter(i => i.id !== id);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user