C55X6B5YBXZ7SVRC4IDCRG6BY5ZW2V6JORGQ2WMQPBAECVLMZOMQC 6CUC3C5BCSMUJU73T3XYWPTVEUYXXG3PREA7P2BRZZ7XZY54JBMAC OWZCU6OX33FKWEEI7LUWIZZTBPUP2OSLJIADPHIBYOWGPPRIPMIAC B7W4Q522DLB6DKH2TFDOCTSZFZLFTOLCT6CCZEOC3V3UUMSAOOFAC AJKCAY3ODMTFBO6GXWXWQSWNFIH3H7JNBRFVW5H6ZSWA7SZGY3FAC Q4BYGYNX3UZXX47EMX2GWX6M6ICSMIMCLQ7HVOYS4HB4RHYI4NEQC 4C7QXSEQ7XGPZDLCUTFSDCORVEMIRVD55IZTCTP6W4QQCCI52CZQC GGREOYIRZE2GH62X7YXQA7IUSSB25ENLQ5OKVJYWPNI462DP37FAC EKERBH2GMXCDZSFXAQP6FGGQTTW3ZENOUM4ZKZVHWAAKGW64YLTAC .json::<WclToken>().await.map_err(anyhow::Error::from)
.json::<TokenResponse>().await?;match res {TokenResponse::Ok(token) => Ok(token),TokenResponse::Err(err) => {error!("an error occurred while refreshing a user token: {:?}", err);return Err(anyhow!("unable to refresh token"));}}
.json::<WclToken>().await.map_err(anyhow::Error::from)
.json::<TokenResponse>().await?;match res {TokenResponse::Ok(token) => Ok(token),TokenResponse::Err(err) => {error!("an error occurred while acquiring a user token: {:?}", err);return Err(anyhow!("unable to acquire token"));}}
}/// Whether we have access to private logs for `guild` / `zone`.async fn private_access(&self, ctx: &Context<'_>, guild: i32, zone: i32) -> Result<bool> {use crate::schema::auth_codes::dsl as auth;let Data { conpool, .. } = ctx.data()?;Ok(auth::auth_codes.filter(auth::team.eq(guild).and(auth::zone.eq(zone))).count().get_result::<i64>(&*conpool.get()?)?> 0)
async fn revoke_team(&self, ctx: &Context<'_>, code: String, team: i64) -> Result<bool> {todo!()
async fn revoke_team(&self,ctx: &Context<'_>,code: String,team: i64,zone: i64,) -> Result<bool> {use crate::schema::{auth_codes::dsl as auth, teams::dsl as teams};let Data {client,conpool,secrets,..} = ctx.data()?;let token = crate::user_auth::token_for_code(&client, &secrets, &code).await?;if !user_validation::privileged_user(&client, &token, team, zone).await? {return Ok(false);}let con = conpool.get()?;con.transaction::<_, anyhow::Error, _>(|| {// it says team, it means guild.diesel::delete(auth::auth_codes.filter(auth::team.eq(team as i32))).execute(&con)?;// not liking the extra round-trips here but w/elet (guild_name, region, server): (String, String, String) = teams::teams.filter(teams::id.eq(team as i32)).select((teams::name, teams::region_slug, teams::server_slug)).first(&con)?;diesel::delete(teams::teams.filter(teams::name.eq(guild_name).and(teams::region_slug.eq(region)).and(teams::server_slug.eq(server)),),).execute(&con)?;Ok(())})?;Ok(true)
-- Your SQL goes herealter table team_statsdrop constraint team_stats_team_fkey,add constraint team_stats_team_fkey foreign key (team) references teams(id) on delete cascade;alter table encounter_statsdrop constraint encounter_stats_team_fkey,add constraint encounter_stats_team_fkey foreign key (team) references teams(id) on delete cascade;alter table fightsdrop constraint fights_log_fkey,add constraint fights_log_fkey foreign key (log) references logs(iid) on delete cascade;alter table logsdrop constraint logs_team_fkey,add constraint logs_team_fkey foreign key (team) references teams(iid) on delete cascade;alter table raid_nightsdrop constraint raid_nights_ts_fkey,add constraint raid_nights_ts_fkey foreign key (ts) references team_stats(id) on delete cascade;
-- This file should undo anything in `up.sql`alter table team_statsdrop constraint team_stats_team_fkey,add constraint team_stats_team_fkey foreign key (team) references teams(id);alter table encounter_statsdrop constraint encounter_stats_team_fkey,add constraint encounter_stats_team_fkey foreign key (team) references teams(id);alter table fightsdrop constraint fights_log_fkey,add constraint fights_log_fkey foreign key (log) references logs(iid);alter table logsdrop constraint logs_team_fkey,add constraint logs_team_fkey foreign key (team) references teams(iid);alter table raid_nightsdrop constraint raid_nights_ts_fkey,add constraint raid_nights_ts_fkey foreign key (ts) references team_stats(id);
export let host = 'prog-stats.emallson.net';if (process.env.NODE_ENV === 'development') {host = 'localhost:9998';}
export function PreAuth({ open, close, guild, zone }: { open: boolean; close: () => void; guild: number; zone: number; }) {
const modalStyle = {content: { top: 'calc(50% - 20em)', bottom: 'auto', left: 'calc(50% - 20em)', width: 'min(40em, 90vw)' }};export function PreAuth({ open, close, guild, zone }: Props) {
<Modal isOpen={open} contentLabel="Authorization Required" style={{content: { top: 'calc(50% - 20em)', bottom: 'auto', left: 'calc(50% - 20em)', width: 'min(40em, 90vw)' }}}>
<Modal isOpen={open} contentLabel="Authorization Required" style={modalStyle}>
<button onClick={redirect.bind(null, guild, zone)} className="py-2 px-4 bg-blue-200 font-bold rounded-lg shadow-md hover:bg-blue-300 focus:outline-none focus:ring-2">Continue</button>
<button onClick={redirect.bind(null, guild, zone, 'authorize')} className="py-2 px-4 bg-blue-200 font-bold rounded-lg shadow-md hover:bg-blue-300 focus:outline-none focus:ring-2">Continue</button>
export function RevokeAuth({ open, close, guild, zone }: Props) {return (<Modal isOpen={open} contentLabel="Revoke Access?" style={modalStyle}><header className="mb-2"><legend className="font-serif text-2xl">Revoke Private Log Access</legend></header><p>In order to revoke access to private logs, you will need to grant access via WarcraftLogs so that we can verify your identity.</p><p className="mt-2">After verification, all data related to this <strong>guild</strong> will be deleted.</p><footer className="grid gap-4 justify-end grid-flow-col mt-2"><button className="underline" onClick={close}>Cancel</button><button onClick={redirect.bind(null, guild, zone, 'revoke')} className="py-2 px-4 bg-red-200 font-bold rounded-lg shadow-md hover:bg-red-300 focus:outline-none focus:ring-2">Revoke Access</button></footer></Modal>)}
export default function Auth() {const query = new URLSearchParams(useLocation().search);const state = JSON.parse(window.localStorage.getItem('auth_state') || '{}');const nonce = query.get('state');const code = query.get('code');
const REVOKE = gql`mutation Revoke($team: Int!, $code: String!, $zone: Int!) {revokeTeam(code: $code, team: $team, zone: $zone)}`;interface AuthProps {code: string;team: number;zone: number;pathname: string;}
const [storeCode, { data, loading, error }] = useMutation(STORE_CODE, { onError: (e) => console.log(e) });
function RequestAccess({ code, team, zone, pathname }: AuthProps) {console.log(code, team, zone);const [storeCode, { called, data, loading, error }] = useMutation(STORE_CODE, { onError: (e) => console.log(e) });console.log(called);
if(!code || state.state !== nonce) {return <div>Invalid authorization state.</div>;
if(data && data.storeCode) {return <Redirect to={pathname} />;} else if(data) {return <div>You do not have access to private or unlisted logs for that guild.</div>;
return <div></div>;}function RevokeAccess({ code, team, zone }: AuthProps) {const [revokeTeam, { called, data, loading, error }] = useMutation(REVOKE, { onError: (e) => console.log(e) });useEffect(() => {if(!called) {revokeTeam({ variables: { code, team, zone }});}}, [code, team, zone]) // eslint-disable-line react-hooks/exhaustive-deps
export default function Auth() {const query = new URLSearchParams(useLocation().search);const state = JSON.parse(window.localStorage.getItem('auth_state') || '{}');const nonce = query.get('state');const code = query.get('code');if(!code || state.state !== nonce) {return <div>Invalid authorization state.</div>;}switch(state.kind) {case 'revoke':return <RevokeAccess code={code} team={state.team} zone={state.zone} pathname={state.pathname} />;case 'authorize':return <RequestAccess code={code} team={state.team} zone={state.zone} pathname={state.pathname} />;default:return null;}}