Skip to content

Commit

Permalink
Merge pull request #747 from sbondCo/user-type-change
Browse files Browse the repository at this point in the history
manage_users: Support swapping users between Watcharr/Proxy users
  • Loading branch information
IRHM authored Jan 1, 2025
2 parents aa67f7e + 9ba1049 commit a029d38
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 24 deletions.
2 changes: 1 addition & 1 deletion server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import (

type UserType uint8

// Assume watcharr user if none of these...
var (
WATCHARR_USER UserType = 0
JELLYFIN_USER UserType = 1
PLEX_USER UserType = 2
// Registered via trusted header auth
Expand Down
15 changes: 13 additions & 2 deletions server/user_manage.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type ManagedUser struct {
}

type UpdateUserRequest struct {
Permissions *int `json:"permissions"`
Permissions *int `json:"permissions"`
Type *UserType `json:"type"`
}

func getAllUsers(db *gorm.DB) ([]ManagedUser, error) {
Expand All @@ -34,7 +35,7 @@ func getAllUsers(db *gorm.DB) ([]ManagedUser, error) {
// Update a user. For management views, for admin to update another user.
func manageUser(db *gorm.DB, userId uint, ur UpdateUserRequest) error {
// Error now if no userId or any UpdateUserRequest property was provided.
if userId == 0 || (ur.Permissions == nil) {
if userId == 0 || (ur.Permissions == nil && ur.Type == nil) {
slog.Error("manageUser: invalid arguments", "user_id", userId)
return errors.New("invalid arguments, ensure a valid userId and at least one property has been provided for updating")
}
Expand All @@ -49,6 +50,16 @@ func manageUser(db *gorm.DB, userId uint, ur UpdateUserRequest) error {
toUpdate["permissions"] = *ur.Permissions
}
}
if ur.Type != nil {
t := *ur.Type
if t == WATCHARR_USER || t == PROXY_USER {
// Currently only swapping between watcharr/proxy user is supported.
slog.Debug("manageUser: User type is being updated.", "new_type", t)
toUpdate["type"] = t
} else {
slog.Warn("manageUser: User type will not be updated. Only watcharr/proxy types are supported for swapping.", "tried_type", t)
}
}
if res := db.Model(&User{}).Where("id = ?", userId).Updates(toUpdate); res.Error != nil {
slog.Error("manageUser: failed to update user in database", "user_id", userId, "error", res.Error)
return errors.New("failed to update user in database")
Expand Down
27 changes: 27 additions & 0 deletions src/lib/user/UserTypeIcon.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { UserType } from "@/types";
import Icon from "../Icon.svelte";
export let type: UserType;
</script>

{#if !type}
<span
style="font-family: 'Rampart One'; font-weight: bold; font-size: 21px; line-height: 20px; user-select: none;"
>
W
</span>
{:else if type == UserType.Jellyfin}
<Icon i="jellyfin" wh={20} />
{:else if type == UserType.Plex}
<Icon i="plex" wh={20} />
{:else if type == UserType.Proxy}
<Icon i="lock-closed" wh={20} />
{:else}
<!-- Unknown type -->
<span
style="font-family: 'Rampart One'; font-weight: bold; font-size: 21px; line-height: 20px; user-select: none;"
>
?
</span>
{/if}
13 changes: 2 additions & 11 deletions src/routes/(app)/manage_users/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { UserPermission, type ManagedUser } from "@/types";
import axios from "axios";
import EditUserModal from "./modals/EditUserModal.svelte";
import UserTypeIcon from "@/lib/user/UserTypeIcon.svelte";
const currentYear = new Date(Date.now()).getFullYear();
Expand Down Expand Up @@ -37,17 +38,7 @@
<tr>
<td class="username">
<div class={`type-${u.type}`}>
{#if u.type == 1}
<Icon i="jellyfin" wh={20} />
{:else if u.type == 2}
<Icon i="plex" wh={20} />
{:else}
<span
style="font-family: 'Rampart One'; font-weight: bold; font-size: 21px; line-height: 20px; user-select: none;"
>
W
</span>
{/if}
<UserTypeIcon type={u.type} />
{u.username}
{#if userHasPermission(u.permissions, UserPermission.PERM_ADMIN)}
<span class="tag">Admin</span>
Expand Down
54 changes: 46 additions & 8 deletions src/routes/(app)/manage_users/modals/EditUserModal.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<script lang="ts">
import Checkbox from "@/lib/Checkbox.svelte";
import DropDown from "@/lib/DropDown.svelte";
import Modal from "@/lib/Modal.svelte";
import Setting from "@/lib/settings/Setting.svelte";
import SettingsList from "@/lib/settings/SettingsList.svelte";
import { userHasPermission } from "@/lib/util/helpers";
import { notify } from "@/lib/util/notify";
import { UserPermission, type ManagedUser } from "@/types";
import { UserPermission, UserType, type ManagedUser } from "@/types";
import axios from "axios";
interface UpdateUserRequest {
permissions?: number;
type?: UserType;
}
export let user: ManagedUser;
Expand All @@ -20,10 +22,12 @@
// Things we have changed
let changedPerms = false;
let originalUser = structuredClone(user);
async function save() {
const changedType = user.type !== originalUser.type;
// If nothing changed.. error
if (!changedPerms) {
if (!changedPerms && !changedType) {
error = "Nothing has been changed";
return;
}
Expand All @@ -33,6 +37,9 @@
if (changedPerms) {
toUpdate["permissions"] = user.permissions;
}
if (changedType) {
toUpdate["type"] = user.type;
}
const res = await axios.post(`/server/users/${user.id}`, toUpdate);
if (res.status === 200) {
notify({
Expand Down Expand Up @@ -62,9 +69,9 @@
<span class="error">{error}!</span>
{/if}

<h3 class="norm">Permissions</h3>

<SettingsList>
<h3 class="norm">Permissions</h3>

<Setting title="Admin" desc="Give user admin, overrides all other permissions." row>
<Checkbox
name="USER_PERM_ADMIN"
Expand Down Expand Up @@ -98,17 +105,48 @@
/>
</Setting>

<h3 class="norm">Other</h3>

<Setting
title="User Type"
desc="The type of this user, affects how they login and certain features. Currently only possible to swap between Watcharr/Proxy types."
>
{#if !user.type || user.type === UserType.Proxy}
<DropDown
placeholder="Unknown"
bind:active={user.type}
options={[
{
id: 0,
value: "Watcharr"
},
// {
// id: UserType.Jellyfin,
// value: "Jellyfin",
// },
// {
// id: UserType.Plex,
// value: "Plex",
// },
{
id: UserType.Proxy,
value: "Proxy"
}
]}
isDropDownItem={true}
/>
{:else}
<p>This option is not supported for this user type yet.</p>
{/if}
</Setting>

<div class="btns">
<button on:click={() => save()}>Save</button>
</div>
</SettingsList>
</Modal>

<style lang="scss">
h3 {
margin-bottom: 10px;
}
.btns {
display: flex;
flex-flow: row;
Expand Down
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export type PosterExtraDetails = {
};

export enum UserType {
// Assume watcharr user if none of these...
Watcharr = 0,
Jellyfin = 1,
Plex = 2,
Proxy = 3
Expand Down Expand Up @@ -978,7 +978,7 @@ export interface TrustedHeaderAuthLogoutDetailsResponse {
export interface DropDownItem {
id: number | string;
value: string;
icon: Icon;
icon?: Icon;
}

export interface ListBoxItem {
Expand Down

0 comments on commit a029d38

Please sign in to comment.