```rust
{
op: "GetSite"
+ data: {
+ auth: Option<String>,
+ }
+
}
```
##### Response
banned: Vec<UserView>,
online: usize, // This is currently broken
version: String,
+ my_user: Option<User_>, // Gives back your user and settings if logged in
}
}
```
};
use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *};
+use serde::{Deserialize, Serialize};
-#[derive(Clone, Queryable, Identifiable, PartialEq, Debug)]
+#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "user_"]
pub struct User_ {
pub id: i32,
pub actor_id: String,
pub name: String,
pub avatar: Option<String>,
- pub email: Option<String>,
+ pub email: Option<String>, // TODO this shouldn't be in this view
pub matrix_user_id: Option<String>,
pub bio: Option<String>,
pub local: bool,
pub admin: bool,
pub banned: bool,
- pub show_avatars: bool,
- pub send_notifications_to_email: bool,
+ pub show_avatars: bool, // TODO this is a setting, probably doesn't need to be here
+ pub send_notifications_to_email: bool, // TODO also never used
pub published: chrono::NaiveDateTime,
pub number_of_posts: i64,
pub post_score: i64,
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
pub id: i32,
- pub username: String,
pub iss: String,
- pub show_nsfw: bool,
- pub theme: String,
- pub default_sort_type: i16,
- pub default_listing_type: i16,
- pub lang: String,
- pub avatar: Option<String>,
- pub show_avatars: bool,
}
impl Claims {
pub fn jwt(user: User_, hostname: String) -> Jwt {
let my_claims = Claims {
id: user.id,
- username: user.name.to_owned(),
iss: hostname,
- show_nsfw: user.show_nsfw,
- theme: user.theme.to_owned(),
- default_sort_type: user.default_sort_type,
- default_listing_type: user.default_listing_type,
- lang: user.lang.to_owned(),
- avatar: user.avatar.to_owned(),
- show_avatars: user.show_avatars.to_owned(),
};
encode(
&Header::default(),
) -> Result<ListCommunitiesResponse, LemmyError> {
let data: &ListCommunities = &self.data;
- let user_claims: Option<Claims> = match &data.auth {
+ // For logged in users, you need to get back subscribed, and settings
+ let user: Option<User_> = match &data.auth {
Some(auth) => match Claims::decode(&auth) {
- Ok(claims) => Some(claims.claims),
+ Ok(claims) => {
+ let user_id = claims.claims.id;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+ Some(user)
+ }
Err(_e) => None,
},
None => None,
};
- let user_id = match &user_claims {
- Some(claims) => Some(claims.id),
+ let user_id = match &user {
+ Some(user) => Some(user.id),
None => None,
};
- let show_nsfw = match &user_claims {
- Some(claims) => claims.show_nsfw,
+ let show_nsfw = match &user {
+ Some(user) => user.show_nsfw,
None => false,
};
) -> Result<GetPostsResponse, LemmyError> {
let data: &GetPosts = &self.data;
- let user_claims: Option<Claims> = match &data.auth {
+ // For logged in users, you need to get back subscribed, and settings
+ let user: Option<User_> = match &data.auth {
Some(auth) => match Claims::decode(&auth) {
- Ok(claims) => Some(claims.claims),
+ Ok(claims) => {
+ let user_id = claims.claims.id;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+ Some(user)
+ }
Err(_e) => None,
},
None => None,
};
- let user_id = match &user_claims {
- Some(claims) => Some(claims.id),
+ let user_id = match &user {
+ Some(user) => Some(user.id),
None => None,
};
- let show_nsfw = match &user_claims {
- Some(claims) => claims.show_nsfw,
+ let show_nsfw = match &user {
+ Some(user) => user.show_nsfw,
None => false,
};
post_view::*,
site::*,
site_view::*,
+ user::*,
user_view::*,
Crud,
SearchType,
}
#[derive(Serialize, Deserialize)]
-pub struct GetSite {}
+pub struct GetSite {
+ auth: Option<String>,
+}
#[derive(Serialize, Deserialize, Clone)]
pub struct SiteResponse {
banned: Vec<UserView>,
pub online: usize,
version: String,
+ my_user: Option<User_>,
}
#[derive(Serialize, Deserialize)]
pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
) -> Result<GetSiteResponse, LemmyError> {
- let _data: &GetSite = &self.data;
+ let data: &GetSite = &self.data;
// TODO refactor this a little
let res = blocking(pool, move |conn| Site::read(conn, 1)).await?;
0
};
+ // Giving back your user, if you're logged in
+ let my_user: Option<User_> = match &data.auth {
+ Some(auth) => match Claims::decode(&auth) {
+ Ok(claims) => {
+ let user_id = claims.claims.id;
+ let mut user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+ user.password_encrypted = "".to_string();
+ user.private_key = None;
+ user.public_key = None;
+ Some(user)
+ }
+ Err(_e) => None,
+ },
+ None => None,
+ };
+
Ok(GetSiteResponse {
site: site_view,
admins,
banned,
online,
version: version::VERSION.to_string(),
+ my_user,
})
}
}
};
let user_id = claims.id;
+ let mut user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+ // TODO add a User_::read_safe() for this.
+ user.password_encrypted = "".to_string();
+ user.private_key = None;
+ user.public_key = None;
let read_site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
banned,
online: 0,
version: version::VERSION.to_string(),
+ my_user: Some(user),
})
}
}
) -> Result<GetUserDetailsResponse, LemmyError> {
let data: &GetUserDetails = &self.data;
- let user_claims: Option<Claims> = match &data.auth {
+ // For logged in users, you need to get back subscribed, and settings
+ let user: Option<User_> = match &data.auth {
Some(auth) => match Claims::decode(&auth) {
- Ok(claims) => Some(claims.claims),
+ Ok(claims) => {
+ let user_id = claims.claims.id;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+ Some(user)
+ }
Err(_e) => None,
},
None => None,
};
- let user_id = match &user_claims {
- Some(claims) => Some(claims.id),
+ let user_id = match &user {
+ Some(user) => Some(user.id),
None => None,
};
- let show_nsfw = match &user_claims {
- Some(claims) => claims.show_nsfw,
+ let show_nsfw = match &user {
+ Some(user) => user.show_nsfw,
None => false,
};
let subject = &format!(
"{} - Private Message from {}",
Settings::get().hostname,
- claims.username
+ user.name,
);
let html = &format!(
"<h1>Private Message</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
- claims.username, &content_slurs_removed, hostname
+ user.name, &content_slurs_removed, hostname
);
match send_email(subject, &email, &recipient_user.name, html) {
Ok(_o) => _o,
let data = res.data as GetSiteResponse;
this.state.enableDownvotes = data.site.enable_downvotes;
this.setState(this.state);
- document.title = `/u/${UserService.Instance.user.username} ${i18n.t(
+ document.title = `/u/${UserService.Instance.user.name} ${i18n.t(
'inbox'
)} - ${data.site.name}`;
}
}
sendUnreadCount() {
- UserService.Instance.user.unreadCount = this.unreadCount();
- UserService.Instance.sub.next({
- user: UserService.Instance.user,
- });
+ UserService.Instance.unreadCountSub.next(this.unreadCount());
}
unreadCount(): number {
toast,
messageToastify,
md,
+ setTheme,
} from '../utils';
-import { i18n } from '../i18next';
+import { i18n, i18nextSetup } from '../i18next';
interface NavbarState {
isLoggedIn: boolean;
admins: Array<UserView>;
searchParam: string;
toggleSearch: boolean;
+ siteLoading: boolean;
}
export class Navbar extends Component<any, NavbarState> {
private wsSub: Subscription;
private userSub: Subscription;
+ private unreadCountSub: Subscription;
private searchTextField: RefObject<HTMLInputElement>;
emptyState: NavbarState = {
- isLoggedIn: UserService.Instance.user !== undefined,
+ isLoggedIn: false,
unreadCount: 0,
replies: [],
mentions: [],
admins: [],
searchParam: '',
toggleSearch: false,
+ siteLoading: true,
};
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
- // Subscribe to user changes
- this.userSub = UserService.Instance.sub.subscribe(user => {
- this.state.isLoggedIn = user.user !== undefined;
- if (this.state.isLoggedIn) {
- this.state.unreadCount = user.user.unreadCount;
- this.requestNotificationPermission();
- }
- this.setState(this.state);
- });
-
this.wsSub = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
() => console.log('complete')
);
- if (this.state.isLoggedIn) {
- this.requestNotificationPermission();
- // TODO couldn't get re-logging in to re-fetch unreads
- this.fetchUnreads();
- }
-
WebSocketService.Instance.getSite();
this.searchTextField = createRef();
}
+ componentDidMount() {
+ // Subscribe to jwt changes
+ this.userSub = UserService.Instance.jwtSub.subscribe(res => {
+ // A login
+ if (res !== undefined) {
+ this.requestNotificationPermission();
+ } else {
+ this.state.isLoggedIn = false;
+ }
+ WebSocketService.Instance.getSite();
+ this.setState(this.state);
+ });
+
+ // Subscribe to unread count changes
+ this.unreadCountSub = UserService.Instance.unreadCountSub.subscribe(res => {
+ this.setState({ unreadCount: res });
+ });
+ }
+
handleSearchParam(i: Navbar, event: any) {
i.state.searchParam = event.target.value;
i.setState(i.state);
componentWillUnmount() {
this.wsSub.unsubscribe();
this.userSub.unsubscribe();
+ this.unreadCountSub.unsubscribe();
}
// TODO class active corresponding to current page
return (
<nav class="navbar navbar-expand-lg navbar-light shadow-sm p-0 px-3">
<div class="container">
- <Link title={this.state.version} class="navbar-brand" to="/">
- {this.state.siteName}
- </Link>
+ {!this.state.siteLoading ? (
+ <Link title={this.state.version} class="navbar-brand" to="/">
+ {this.state.siteName}
+ </Link>
+ ) : (
+ <div class="navbar-item">
+ <svg class="icon icon-spinner spin">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ </div>
+ )}
{this.state.isLoggedIn && (
<Link
class="ml-auto p-0 navbar-toggler nav-link border-0"
>
<span class="navbar-toggler-icon"></span>
</button>
- <div
- className={`${!this.state.expanded && 'collapse'} navbar-collapse`}
- >
- <ul class="navbar-nav my-2 mr-auto">
- <li class="nav-item">
- <Link
- class="nav-link"
- to="/communities"
- title={i18n.t('communities')}
- >
- {i18n.t('communities')}
- </Link>
- </li>
- <li class="nav-item">
- <Link
- class="nav-link"
- to={{
- pathname: '/create_post',
- state: { prevPath: this.currentLocation },
- }}
- title={i18n.t('create_post')}
- >
- {i18n.t('create_post')}
- </Link>
- </li>
- <li class="nav-item">
- <Link
- class="nav-link"
- to="/create_community"
- title={i18n.t('create_community')}
- >
- {i18n.t('create_community')}
- </Link>
- </li>
- <li className="nav-item">
- <Link
- class="nav-link"
- to="/sponsors"
- title={i18n.t('donate_to_lemmy')}
- >
- <svg class="icon">
- <use xlinkHref="#icon-coffee"></use>
- </svg>
- </Link>
- </li>
- </ul>
- {!this.context.router.history.location.pathname.match(
- /^\/search/
- ) && (
- <form
- class="form-inline"
- onSubmit={linkEvent(this, this.handleSearchSubmit)}
- >
- <input
- class={`form-control mr-0 search-input ${
- this.state.toggleSearch ? 'show-input' : 'hide-input'
- }`}
- onInput={linkEvent(this, this.handleSearchParam)}
- value={this.state.searchParam}
- ref={this.searchTextField}
- type="text"
- placeholder={i18n.t('search')}
- onBlur={linkEvent(this, this.handleSearchBlur)}
- ></input>
- <button
- name="search-btn"
- onClick={linkEvent(this, this.handleSearchBtn)}
- class="btn btn-link"
- style="color: var(--gray)"
- >
- <svg class="icon">
- <use xlinkHref="#icon-search"></use>
- </svg>
- </button>
- </form>
- )}
- <ul class="navbar-nav my-2">
- {this.canAdmin && (
+ {!this.state.siteLoading && (
+ <div
+ className={`${
+ !this.state.expanded && 'collapse'
+ } navbar-collapse`}
+ >
+ <ul class="navbar-nav my-2 mr-auto">
+ <li class="nav-item">
+ <Link
+ class="nav-link"
+ to="/communities"
+ title={i18n.t('communities')}
+ >
+ {i18n.t('communities')}
+ </Link>
+ </li>
+ <li class="nav-item">
+ <Link
+ class="nav-link"
+ to={{
+ pathname: '/create_post',
+ state: { prevPath: this.currentLocation },
+ }}
+ title={i18n.t('create_post')}
+ >
+ {i18n.t('create_post')}
+ </Link>
+ </li>
+ <li class="nav-item">
+ <Link
+ class="nav-link"
+ to="/create_community"
+ title={i18n.t('create_community')}
+ >
+ {i18n.t('create_community')}
+ </Link>
+ </li>
<li className="nav-item">
<Link
class="nav-link"
- to={`/admin`}
- title={i18n.t('admin_settings')}
+ to="/sponsors"
+ title={i18n.t('donate_to_lemmy')}
>
<svg class="icon">
- <use xlinkHref="#icon-settings"></use>
+ <use xlinkHref="#icon-coffee"></use>
</svg>
</Link>
</li>
+ </ul>
+ {!this.context.router.history.location.pathname.match(
+ /^\/search/
+ ) && (
+ <form
+ class="form-inline"
+ onSubmit={linkEvent(this, this.handleSearchSubmit)}
+ >
+ <input
+ class={`form-control mr-0 search-input ${
+ this.state.toggleSearch ? 'show-input' : 'hide-input'
+ }`}
+ onInput={linkEvent(this, this.handleSearchParam)}
+ value={this.state.searchParam}
+ ref={this.searchTextField}
+ type="text"
+ placeholder={i18n.t('search')}
+ onBlur={linkEvent(this, this.handleSearchBlur)}
+ ></input>
+ <button
+ name="search-btn"
+ onClick={linkEvent(this, this.handleSearchBtn)}
+ class="btn btn-link"
+ style="color: var(--gray)"
+ >
+ <svg class="icon">
+ <use xlinkHref="#icon-search"></use>
+ </svg>
+ </button>
+ </form>
)}
- </ul>
- {this.state.isLoggedIn ? (
- <>
- <ul class="navbar-nav my-2">
+ <ul class="navbar-nav my-2">
+ {this.canAdmin && (
<li className="nav-item">
- <Link class="nav-link" to="/inbox" title={i18n.t('inbox')}>
+ <Link
+ class="nav-link"
+ to={`/admin`}
+ title={i18n.t('admin_settings')}
+ >
<svg class="icon">
- <use xlinkHref="#icon-bell"></use>
+ <use xlinkHref="#icon-settings"></use>
</svg>
- {this.state.unreadCount > 0 && (
- <span class="ml-1 badge badge-light">
- {this.state.unreadCount}
- </span>
- )}
</Link>
</li>
- </ul>
- <ul class="navbar-nav">
+ )}
+ </ul>
+ {this.state.isLoggedIn ? (
+ <>
+ <ul class="navbar-nav my-2">
+ <li className="nav-item">
+ <Link
+ class="nav-link"
+ to="/inbox"
+ title={i18n.t('inbox')}
+ >
+ <svg class="icon">
+ <use xlinkHref="#icon-bell"></use>
+ </svg>
+ {this.state.unreadCount > 0 && (
+ <span class="ml-1 badge badge-light">
+ {this.state.unreadCount}
+ </span>
+ )}
+ </Link>
+ </li>
+ </ul>
+ <ul class="navbar-nav">
+ <li className="nav-item">
+ <Link
+ class="nav-link"
+ to={`/u/${UserService.Instance.user.name}`}
+ title={i18n.t('settings')}
+ >
+ <span>
+ {UserService.Instance.user.avatar &&
+ showAvatars() && (
+ <img
+ src={pictrsAvatarThumbnail(
+ UserService.Instance.user.avatar
+ )}
+ height="32"
+ width="32"
+ class="rounded-circle mr-2"
+ />
+ )}
+ {UserService.Instance.user.name}
+ </span>
+ </Link>
+ </li>
+ </ul>
+ </>
+ ) : (
+ <ul class="navbar-nav my-2">
<li className="nav-item">
<Link
- class="nav-link"
- to={`/u/${UserService.Instance.user.username}`}
- title={i18n.t('settings')}
+ class="btn btn-success"
+ to="/login"
+ title={i18n.t('login_sign_up')}
>
- <span>
- {UserService.Instance.user.avatar && showAvatars() && (
- <img
- src={pictrsAvatarThumbnail(
- UserService.Instance.user.avatar
- )}
- height="32"
- width="32"
- class="rounded-circle mr-2"
- />
- )}
- {UserService.Instance.user.username}
- </span>
+ {i18n.t('login_sign_up')}
</Link>
</li>
</ul>
- </>
- ) : (
- <ul class="navbar-nav my-2">
- <li className="nav-item">
- <Link
- class="btn btn-success"
- to="/login"
- title={i18n.t('login_sign_up')}
- >
- {i18n.t('login_sign_up')}
- </Link>
- </li>
- </ul>
- )}
- </div>
+ )}
+ </div>
+ )}
</div>
</nav>
);
this.state.siteName = data.site.name;
this.state.version = data.version;
this.state.admins = data.admins;
- this.setState(this.state);
}
- }
- }
- fetchUnreads() {
- if (this.state.isLoggedIn) {
- let repliesForm: GetRepliesForm = {
- sort: SortType[SortType.New],
- unread_only: true,
- page: 1,
- limit: fetchLimit,
- };
+ // The login
+ if (data.my_user) {
+ UserService.Instance.user = data.my_user;
+ // On the first load, check the unreads
+ if (this.state.isLoggedIn == false) {
+ this.requestNotificationPermission();
+ this.fetchUnreads();
+ setTheme(data.my_user.theme, true);
+ }
+ this.state.isLoggedIn = true;
+ }
- let userMentionsForm: GetUserMentionsForm = {
- sort: SortType[SortType.New],
- unread_only: true,
- page: 1,
- limit: fetchLimit,
- };
+ i18nextSetup();
- let privateMessagesForm: GetPrivateMessagesForm = {
- unread_only: true,
- page: 1,
- limit: fetchLimit,
- };
+ this.state.siteLoading = false;
+ this.setState(this.state);
+ }
+ }
- if (this.currentLocation !== '/inbox') {
- WebSocketService.Instance.getReplies(repliesForm);
- WebSocketService.Instance.getUserMentions(userMentionsForm);
- WebSocketService.Instance.getPrivateMessages(privateMessagesForm);
- }
+ fetchUnreads() {
+ console.log('Fetching unreads...');
+ let repliesForm: GetRepliesForm = {
+ sort: SortType[SortType.New],
+ unread_only: true,
+ page: 1,
+ limit: fetchLimit,
+ };
+
+ let userMentionsForm: GetUserMentionsForm = {
+ sort: SortType[SortType.New],
+ unread_only: true,
+ page: 1,
+ limit: fetchLimit,
+ };
+
+ let privateMessagesForm: GetPrivateMessagesForm = {
+ unread_only: true,
+ page: 1,
+ limit: fetchLimit,
+ };
+
+ if (this.currentLocation !== '/inbox') {
+ WebSocketService.Instance.getReplies(repliesForm);
+ WebSocketService.Instance.getUserMentions(userMentionsForm);
+ WebSocketService.Instance.getPrivateMessages(privateMessagesForm);
}
}
}
sendUnreadCount() {
- UserService.Instance.user.unreadCount = this.state.unreadCount;
- UserService.Instance.sub.next({
- user: UserService.Instance.user,
- });
+ UserService.Instance.unreadCountSub.next(this.state.unreadCount);
}
calculateUnreadCount(): number {
auth: null,
};
WebSocketService.Instance.markCommentAsRead(form);
- UserService.Instance.user.unreadCount--;
- UserService.Instance.sub.next({
- user: UserService.Instance.user,
- });
+ UserService.Instance.unreadCountSub.next(
+ UserService.Instance.unreadCountSub.value - 1
+ );
}
}
return format === 'uppercase' ? value.toUpperCase() : value;
}
-i18next.init({
- debug: false,
- // load: 'languageOnly',
-
- // initImmediate: false,
- lng: getLanguage(),
- fallbackLng: 'en',
- resources,
- interpolation: { format },
-});
+export function i18nextSetup() {
+ i18next.init({
+ debug: false,
+ // load: 'languageOnly',
+ // initImmediate: false,
+ lng: getLanguage(),
+ fallbackLng: 'en',
+ resources,
+ interpolation: { format },
+ });
+}
export { i18next as i18n, resources };
Url,
}
-export interface User {
+export interface Claims {
id: number;
iss: string;
- username: string;
+}
+
+export interface User {
+ id: number;
+ name: string;
+ preferred_username?: string;
+ email?: string;
+ avatar?: string;
+ admin: boolean;
+ banned: boolean;
+ published: string;
+ updated?: string;
show_nsfw: boolean;
theme: string;
default_sort_type: SortType;
default_listing_type: ListingType;
lang: string;
- avatar?: string;
show_avatars: boolean;
- unreadCount?: number;
+ send_notifications_to_email: boolean;
+ matrix_user_id?: string;
+ actor_id: string;
+ bio?: string;
+ local: boolean;
+ last_refreshed_at: string;
}
export interface UserView {
auth?: string;
}
+export interface GetSiteForm {
+ auth?: string;
+}
+
export interface GetSiteConfigResponse {
config_hjson: string;
}
banned: Array<UserView>;
online: number;
version: string;
+ my_user?: User;
}
export interface SiteResponse {
| AddAdminResponse
| PrivateMessageResponse
| PrivateMessagesResponse
- | GetSiteConfigResponse;
+ | GetSiteConfigResponse
+ | GetSiteResponse;
export interface WebSocketResponse {
op: UserOperation;
import Cookies from 'js-cookie';
-import { User, LoginResponse } from '../interfaces';
+import { User, Claims, LoginResponse } from '../interfaces';
import { setTheme } from '../utils';
import jwt_decode from 'jwt-decode';
-import { Subject } from 'rxjs';
+import { Subject, BehaviorSubject } from 'rxjs';
export class UserService {
private static _instance: UserService;
public user: User;
- public sub: Subject<{ user: User }> = new Subject<{
- user: User;
- }>();
+ public claims: Claims;
+ public jwtSub: Subject<string> = new Subject<string>();
+ public unreadCountSub: BehaviorSubject<number> = new BehaviorSubject<number>(
+ 0
+ );
private constructor() {
let jwt = Cookies.get('jwt');
if (jwt) {
- this.setUser(jwt);
+ this.setClaims(jwt);
} else {
setTheme();
console.log('No JWT cookie found.');
}
public login(res: LoginResponse) {
- this.setUser(res.jwt);
+ this.setClaims(res.jwt);
Cookies.set('jwt', res.jwt, { expires: 365 });
console.log('jwt cookie set');
}
public logout() {
+ this.claims = undefined;
this.user = undefined;
Cookies.remove('jwt');
setTheme();
- this.sub.next({ user: undefined });
+ this.jwtSub.next(undefined);
console.log('Logged out.');
}
return Cookies.get('jwt');
}
- private setUser(jwt: string) {
- this.user = jwt_decode(jwt);
- setTheme(this.user.theme, true);
- this.sub.next({ user: this.user });
- console.log(this.user);
+ private setClaims(jwt: string) {
+ this.claims = jwt_decode(jwt);
+ this.jwtSub.next(jwt);
}
public static get Instance() {
GetCommentsForm,
UserJoinForm,
GetSiteConfig,
+ GetSiteForm,
SiteConfigForm,
MessageType,
WebSocketJsonResponse,
this.ws.send(this.wsSendWrapper(UserOperation.EditSite, siteForm));
}
- public getSite() {
- this.ws.send(this.wsSendWrapper(UserOperation.GetSite, {}));
+ public getSite(form: GetSiteForm = {}) {
+ this.setAuth(form, false);
+ this.ws.send(this.wsSendWrapper(UserOperation.GetSite, form));
}
public getSiteConfig() {