119 lines
6.6 KiB
PL/PgSQL
119 lines
6.6 KiB
PL/PgSQL
-- Sun Catering v17.8 developer-panel additions.
|
||
-- Applied to the current project on 2026-09-01.
|
||
|
||
create or replace function public.sun_platform_list_users()
|
||
returns table(
|
||
user_id uuid,
|
||
email text,
|
||
last_sign_in_at timestamptz,
|
||
created_at timestamptz,
|
||
workspace_id uuid,
|
||
workspace_name text,
|
||
role text,
|
||
display_name text,
|
||
is_active boolean,
|
||
is_platform_admin boolean
|
||
)
|
||
language plpgsql
|
||
stable
|
||
security definer
|
||
set search_path='public'
|
||
as $$
|
||
begin
|
||
if not public.sun_is_platform_admin() then raise exception 'Platform administrator required'; end if;
|
||
return query
|
||
select u.id,u.email::text,u.last_sign_in_at,u.created_at,m.workspace_id,w.name,m.role,m.display_name,m.is_active,
|
||
exists(select 1 from public.sun_platform_admins p where p.user_id=u.id)
|
||
from auth.users u
|
||
left join public.sun_workspace_members m on m.user_id=u.id
|
||
left join public.sun_workspaces w on w.id=m.workspace_id
|
||
order by coalesce(w.name,''),coalesce(m.display_name,u.email),u.email;
|
||
end;
|
||
$$;
|
||
revoke all on function public.sun_platform_list_users() from public;
|
||
grant execute on function public.sun_platform_list_users() to authenticated;
|
||
|
||
create or replace function public.sun_v17_create_backup(p_workspace uuid, p_kind text default 'manual'::text, p_label text default ''::text)
|
||
returns uuid
|
||
language plpgsql
|
||
security definer
|
||
set search_path='public'
|
||
as $$
|
||
declare v_id uuid; v_kind text:=lower(coalesce(p_kind,'manual'));
|
||
begin
|
||
if public.sun_member_role(p_workspace) is null and not public.sun_is_platform_admin() then raise exception 'Access denied'; end if;
|
||
if v_kind not in ('daily','manual','pre_restore','migration') then raise exception 'Invalid backup kind'; end if;
|
||
if v_kind<>'daily' and not public.sun_is_platform_admin() then raise exception 'Platform administrator required'; end if;
|
||
if v_kind='daily' and exists(select 1 from public.sun_v17_backups where workspace_id=p_workspace and kind='daily' and created_at::date=current_date) then
|
||
select id into v_id from public.sun_v17_backups where workspace_id=p_workspace and kind='daily' and created_at::date=current_date order by created_at desc limit 1;
|
||
return v_id;
|
||
end if;
|
||
insert into public.sun_v17_backups(workspace_id,kind,label,snapshot,created_by)
|
||
values(p_workspace,v_kind,left(coalesce(p_label,''),240),public.sun_v17_build_snapshot(p_workspace),auth.uid()) returning id into v_id;
|
||
insert into public.sun_v17_workspace_meta(workspace_id,last_backup_on,updated_at) values(p_workspace,current_date,now())
|
||
on conflict(workspace_id) do update set last_backup_on=current_date,updated_at=now();
|
||
return v_id;
|
||
end;
|
||
$$;
|
||
|
||
create or replace function public.sun_v17_restore_backup(p_workspace uuid, p_backup uuid)
|
||
returns void
|
||
language plpgsql
|
||
security definer
|
||
set search_path='public'
|
||
as $$
|
||
declare s jsonb; legacy jsonb;
|
||
begin
|
||
if not public.sun_is_platform_admin() then raise exception 'Platform administrator required'; end if;
|
||
perform public.sun_v17_create_backup(p_workspace,'pre_restore','Автоматически перед восстановлением');
|
||
select snapshot into s from public.sun_v17_backups where id=p_backup and workspace_id=p_workspace;
|
||
if s is null then raise exception 'Backup not found'; end if;
|
||
legacy:=s->'legacy';
|
||
if legacy is null or jsonb_typeof(legacy)<>'object' then raise exception 'Backup has no legacy state'; end if;
|
||
perform public.sun_save_app_state(p_workspace,legacy,'backup-restore');
|
||
perform public.sun_v17_mirror_legacy(p_workspace,legacy,'backup-restore');
|
||
insert into public.sun_v17_change_events(workspace_id,entity,entity_key,operation,client_id,created_by)
|
||
values(p_workspace,'workspace','backup','restore','backup-restore',auth.uid());
|
||
end;
|
||
$$;
|
||
revoke all on function public.sun_v17_create_backup(uuid,text,text) from public;
|
||
revoke all on function public.sun_v17_restore_backup(uuid,uuid) from public;
|
||
grant execute on function public.sun_v17_create_backup(uuid,text,text) to authenticated;
|
||
grant execute on function public.sun_v17_restore_backup(uuid,uuid) to authenticated;
|
||
|
||
-- Company owner can attach an already registered account by email without invite codes.
|
||
create or replace function public.sun_owner_add_existing_member(p_workspace uuid,p_email text,p_role text default 'manager')
|
||
returns uuid
|
||
language plpgsql
|
||
security definer
|
||
set search_path='public'
|
||
as $$
|
||
declare
|
||
v_user uuid;
|
||
v_role text:=lower(coalesce(p_role,'manager'));
|
||
v_display text;
|
||
v_max integer;
|
||
v_count integer;
|
||
begin
|
||
if auth.uid() is null then raise exception 'Authentication required'; end if;
|
||
if public.sun_member_role(p_workspace)<>'admin' and not public.sun_has_permission(p_workspace,'users.manage') then raise exception 'Нет права управлять сотрудниками'; end if;
|
||
if public.sun_subscription_access_mode(p_workspace)<>'full' then raise exception 'Подписка не позволяет изменять пользователей'; end if;
|
||
if not public.sun_workspace_has_feature(p_workspace,'users_manage') then raise exception 'Сотрудники недоступны на текущем тарифе'; end if;
|
||
if v_role not in ('manager','kitchen','courier','viewer') then raise exception 'Для сотрудника выберите рабочую роль'; end if;
|
||
select id,coalesce(nullif(raw_user_meta_data->>'name',''),split_part(email,'@',1)) into v_user,v_display
|
||
from auth.users where lower(email)=lower(trim(p_email)) limit 1;
|
||
if v_user is null then raise exception 'Аккаунт с таким email ещё не зарегистрирован'; end if;
|
||
select p.max_members into v_max from public.sun_workspace_subscriptions s join public.sun_plans p on p.id=s.plan_id where s.workspace_id=p_workspace;
|
||
select count(*)::int into v_count from public.sun_workspace_members where workspace_id=p_workspace and is_active=true;
|
||
if not exists(select 1 from public.sun_workspace_members where workspace_id=p_workspace and user_id=v_user and is_active=true) then
|
||
if v_max is not null and v_count>=v_max then raise exception 'Достигнут лимит сотрудников тарифа (%)',v_max; end if;
|
||
end if;
|
||
insert into public.sun_workspace_members(workspace_id,user_id,role,display_name,is_active,permissions,updated_at)
|
||
values(p_workspace,v_user,v_role,v_display,true,public.sun_role_default_permissions(v_role),now())
|
||
on conflict(workspace_id,user_id) do update set role=excluded.role,display_name=coalesce(public.sun_workspace_members.display_name,excluded.display_name),is_active=true,permissions=excluded.permissions,updated_at=now();
|
||
return v_user;
|
||
end;
|
||
$$;
|
||
revoke all on function public.sun_owner_add_existing_member(uuid,text,text) from public;
|
||
grant execute on function public.sun_owner_add_existing_member(uuid,text,text) to authenticated;
|