<|start_filename|>core/server/lib/members/static/auth/styles/utils.css<|end_filename|>
/* Layout Utitlities */
/* ------------------------------------------------------------

These are generic CSS classes that can be used on containers 
that have the single purpose of setting up layout.

*/


/* Flexbox */
/* ------------------------------------------------------------ */

.flex { display: flex; }
.inline-flex { display: inline-flex; }

/* 1. Fix for Chrome 44 bug.
 * https://code.google.com/p/chromium/issues/detail?id=506893 */
.flex-auto {
    flex: 1 1 auto;
    min-width: 0; /* 1 */
    min-height: 0; /* 1 */
}

.flex-none { flex: none; }

.flex-column  { flex-direction: column; }
.flex-row     { flex-direction: row; }
.flex-wrap    { flex-wrap: wrap; }
.flex-nowrap    { flex-wrap: nowrap; }
.flex-wrap-reverse    { flex-wrap: wrap-reverse; }
.flex-column-reverse  { flex-direction: column-reverse; }
.flex-row-reverse     { flex-direction: row-reverse; }

.items-start    { align-items: flex-start; }
.items-end      { align-items: flex-end; }
.items-center   { align-items: center; }
.items-baseline { align-items: baseline; }
.items-stretch  { align-items: stretch; }

.self-start    { align-self: flex-start; }
.self-end      { align-self: flex-end; }
.self-center   { align-self: center; }
.self-baseline { align-self: baseline; }
.self-stretch  { align-self: stretch; }

.justify-start   { justify-content: flex-start; }
.justify-end     { justify-content: flex-end; }
.justify-center  { justify-content: center; }
.justify-between { justify-content: space-between; }
.justify-around  { justify-content: space-around; }

.content-start   { align-content: flex-start; }
.content-end     { align-content: flex-end; }
.content-center  { align-content: center; }
.content-between { align-content: space-between; }
.content-around  { align-content: space-around; }
.content-stretch { align-content: stretch; }

.order-0 { order: 0; }
.order-1 { order: 1; }
.order-2 { order: 2; }
.order-3 { order: 3; }
.order-4 { order: 4; }
.order-5 { order: 5; }
.order-6 { order: 6; }
.order-7 { order: 7; }
.order-8 { order: 8; }
.order-last { order: 99999; }

.flex-grow-0 { flex-grow: 0; }
.flex-grow-1 { flex-grow: 1; }

.flex-shrink-0 { flex-shrink: 0; }
.flex-shrink-1 { flex-shrink: 1; }


/* Margins and paddings */
/* ------------------------------------------------------------ */
:root {
    --grid-size: 0.4rem;
}

.pa0 {    padding: 0; }
.pa1 {    padding: calc(var(--grid-size) * 1); }
.pa2 {    padding: calc(var(--grid-size) * 2); }
.pa3 {    padding: calc(var(--grid-size) * 3); }
.pa4 {    padding: calc(var(--grid-size) * 4); }
.pa5 {    padding: calc(var(--grid-size) * 5); }
.pa6 {    padding: calc(var(--grid-size) * 6); }
.pa7 {    padding: calc(var(--grid-size) * 7); }
.pa8 {    padding: calc(var(--grid-size) * 8); }
.pa9 {    padding: calc(var(--grid-size) * 9); }
.pa10 {    padding: calc(var(--grid-size) * 10); }
.pa11 {    padding: calc(var(--grid-size) * 11); }
.pa12 {    padding: calc(var(--grid-size) * 12); }
.pa13 {    padding: calc(var(--grid-size) * 13); }
.pa14 {    padding: calc(var(--grid-size) * 14); }
.pa15 {    padding: calc(var(--grid-size) * 15); }
.pa16 {    padding: calc(var(--grid-size) * 16); }
.pa17 {    padding: calc(var(--grid-size) * 17); }
.pa18 {    padding: calc(var(--grid-size) * 18); }
.pa19 {    padding: calc(var(--grid-size) * 19); }
.pa20 {    padding: calc(var(--grid-size) * 20); }
.pa25 {    padding: calc(var(--grid-size) * 25); }
.pa30 {    padding: calc(var(--grid-size) * 30); }
.pa40 {    padding: calc(var(--grid-size) * 40); }
.pa50 {    padding: calc(var(--grid-size) * 50); }

.pr0 {    padding-right: 0; }
.pr1 {    padding-right: calc(var(--grid-size) * 1); }
.pr2 {    padding-right: calc(var(--grid-size) * 2); }
.pr3 {    padding-right: calc(var(--grid-size) * 3); }
.pr4 {    padding-right: calc(var(--grid-size) * 4); }
.pr5 {    padding-right: calc(var(--grid-size) * 5); }
.pr6 {    padding-right: calc(var(--grid-size) * 6); }
.pr7 {    padding-right: calc(var(--grid-size) * 7); }
.pr8 {    padding-right: calc(var(--grid-size) * 8); }
.pr9 {    padding-right: calc(var(--grid-size) * 9); }
.pr10 {    padding-right: calc(var(--grid-size) * 10); }
.pr11 {    padding-right: calc(var(--grid-size) * 11); }
.pr12 {    padding-right: calc(var(--grid-size) * 12); }
.pr13 {    padding-right: calc(var(--grid-size) * 13); }
.pr14 {    padding-right: calc(var(--grid-size) * 14); }
.pr15 {    padding-right: calc(var(--grid-size) * 15); }
.pr16 {    padding-right: calc(var(--grid-size) * 16); }
.pr17 {    padding-right: calc(var(--grid-size) * 17); }
.pr18 {    padding-right: calc(var(--grid-size) * 18); }
.pr19 {    padding-right: calc(var(--grid-size) * 19); }
.pr20 {    padding-right: calc(var(--grid-size) * 20); }
.pr25 {    padding-right: calc(var(--grid-size) * 25); }
.pr30 {    padding-right: calc(var(--grid-size) * 30); }
.pr40 {    padding-right: calc(var(--grid-size) * 40); }
.pr50 {    padding-right: calc(var(--grid-size) * 50); }

.pb0 {    padding-bottom: 0; }
.pb1 {    padding-bottom: calc(var(--grid-size) * 1); }
.pb2 {    padding-bottom: calc(var(--grid-size) * 2); }
.pb3 {    padding-bottom: calc(var(--grid-size) * 3); }
.pb4 {    padding-bottom: calc(var(--grid-size) * 4); }
.pb5 {    padding-bottom: calc(var(--grid-size) * 5); }
.pb6 {    padding-bottom: calc(var(--grid-size) * 6); }
.pb7 {    padding-bottom: calc(var(--grid-size) * 7); }
.pb8 {    padding-bottom: calc(var(--grid-size) * 8); }
.pb9 {    padding-bottom: calc(var(--grid-size) * 9); }
.pb10 {    padding-bottom: calc(var(--grid-size) * 10); }
.pb11 {    padding-bottom: calc(var(--grid-size) * 11); }
.pb12 {    padding-bottom: calc(var(--grid-size) * 12); }
.pb13 {    padding-bottom: calc(var(--grid-size) * 13); }
.pb14 {    padding-bottom: calc(var(--grid-size) * 14); }
.pb15 {    padding-bottom: calc(var(--grid-size) * 15); }
.pb16 {    padding-bottom: calc(var(--grid-size) * 16); }
.pb17 {    padding-bottom: calc(var(--grid-size) * 17); }
.pb18 {    padding-bottom: calc(var(--grid-size) * 18); }
.pb19 {    padding-bottom: calc(var(--grid-size) * 19); }
.pb20 {    padding-bottom: calc(var(--grid-size) * 20); }
.pb25 {    padding-bottom: calc(var(--grid-size) * 25); }
.pb30 {    padding-bottom: calc(var(--grid-size) * 30); }
.pb40 {    padding-bottom: calc(var(--grid-size) * 40); }
.pb50 {    padding-bottom: calc(var(--grid-size) * 50); }

.pl0 {    padding-left: 0; }
.pl1 {    padding-left: calc(var(--grid-size) * 1); }
.pl2 {    padding-left: calc(var(--grid-size) * 2); }
.pl3 {    padding-left: calc(var(--grid-size) * 3); }
.pl4 {    padding-left: calc(var(--grid-size) * 4); }
.pl5 {    padding-left: calc(var(--grid-size) * 5); }
.pl6 {    padding-left: calc(var(--grid-size) * 6); }
.pl7 {    padding-left: calc(var(--grid-size) * 7); }
.pl8 {    padding-left: calc(var(--grid-size) * 8); }
.pl9 {    padding-left: calc(var(--grid-size) * 9); }
.pl10 {    padding-left: calc(var(--grid-size) * 10); }
.pl11 {    padding-left: calc(var(--grid-size) * 11); }
.pl12 {    padding-left: calc(var(--grid-size) * 12); }
.pl13 {    padding-left: calc(var(--grid-size) * 13); }
.pl14 {    padding-left: calc(var(--grid-size) * 14); }
.pl15 {    padding-left: calc(var(--grid-size) * 15); }
.pl16 {    padding-left: calc(var(--grid-size) * 16); }
.pl17 {    padding-left: calc(var(--grid-size) * 17); }
.pl18 {    padding-left: calc(var(--grid-size) * 18); }
.pl19 {    padding-left: calc(var(--grid-size) * 19); }
.pl20 {    padding-left: calc(var(--grid-size) * 20); }
.pl25 {    padding-left: calc(var(--grid-size) * 25); }
.pl30 {    padding-left: calc(var(--grid-size) * 30); }
.pl40 {    padding-left: calc(var(--grid-size) * 40); }
.pl50 {    padding-left: calc(var(--grid-size) * 50); }

.pt0 {    padding-top: 0; }
.pt1 {    padding-top: calc(var(--grid-size) * 1); }
.pt2 {    padding-top: calc(var(--grid-size) * 2); }
.pt3 {    padding-top: calc(var(--grid-size) * 3); }
.pt4 {    padding-top: calc(var(--grid-size) * 4); }
.pt5 {    padding-top: calc(var(--grid-size) * 5); }
.pt6 {    padding-top: calc(var(--grid-size) * 6); }
.pt7 {    padding-top: calc(var(--grid-size) * 7); }
.pt8 {    padding-top: calc(var(--grid-size) * 8); }
.pt9 {    padding-top: calc(var(--grid-size) * 9); }
.pt10 {    padding-top: calc(var(--grid-size) * 10); }
.pt11 {    padding-top: calc(var(--grid-size) * 11); }
.pt12 {    padding-top: calc(var(--grid-size) * 12); }
.pt13 {    padding-top: calc(var(--grid-size) * 13); }
.pt14 {    padding-top: calc(var(--grid-size) * 14); }
.pt15 {    padding-top: calc(var(--grid-size) * 15); }
.pt16 {    padding-top: calc(var(--grid-size) * 16); }
.pt17 {    padding-top: calc(var(--grid-size) * 17); }
.pt18 {    padding-top: calc(var(--grid-size) * 18); }
.pt19 {    padding-top: calc(var(--grid-size) * 19); }
.pt20 {    padding-top: calc(var(--grid-size) * 20); }
.pt25 {    padding-top: calc(var(--grid-size) * 25); }
.pt30 {    padding-top: calc(var(--grid-size) * 30); }
.pt40 {    padding-top: calc(var(--grid-size) * 40); }
.pt50 {    padding-top: calc(var(--grid-size) * 50); }

.ma0 {    margin: 0; }
.ma1 {    margin: calc(var(--grid-size) * 1); }
.ma2 {    margin: calc(var(--grid-size) * 2); }
.ma3 {    margin: calc(var(--grid-size) * 3); }
.ma4 {    margin: calc(var(--grid-size) * 4); }
.ma5 {    margin: calc(var(--grid-size) * 5); }
.ma6 {    margin: calc(var(--grid-size) * 6); }
.ma7 {    margin: calc(var(--grid-size) * 7); }
.ma8 {    margin: calc(var(--grid-size) * 8); }
.ma9 {    margin: calc(var(--grid-size) * 9); }
.ma10 {    margin: calc(var(--grid-size) * 10); }
.ma11 {    margin: calc(var(--grid-size) * 11); }
.ma12 {    margin: calc(var(--grid-size) * 12); }
.ma13 {    margin: calc(var(--grid-size) * 13); }
.ma14 {    margin: calc(var(--grid-size) * 14); }
.ma15 {    margin: calc(var(--grid-size) * 15); }
.ma16 {    margin: calc(var(--grid-size) * 16); }
.ma17 {    margin: calc(var(--grid-size) * 17); }
.ma18 {    margin: calc(var(--grid-size) * 18); }
.ma19 {    margin: calc(var(--grid-size) * 19); }
.ma20 {    margin: calc(var(--grid-size) * 20); }
.ma25 {    margin: calc(var(--grid-size) * 25); }
.ma30 {    margin: calc(var(--grid-size) * 30); }
.ma40 {    margin: calc(var(--grid-size) * 40); }
.ma50 {    margin: calc(var(--grid-size) * 50); }

.mr0 {    margin-right: 0; }
.mr1 {    margin-right: calc(var(--grid-size) * 1); }
.mr2 {    margin-right: calc(var(--grid-size) * 2); }
.mr3 {    margin-right: calc(var(--grid-size) * 3); }
.mr4 {    margin-right: calc(var(--grid-size) * 4); }
.mr5 {    margin-right: calc(var(--grid-size) * 5); }
.mr6 {    margin-right: calc(var(--grid-size) * 6); }
.mr7 {    margin-right: calc(var(--grid-size) * 7); }
.mr8 {    margin-right: calc(var(--grid-size) * 8); }
.mr9 {    margin-right: calc(var(--grid-size) * 9); }
.mr10 {    margin-right: calc(var(--grid-size) * 10); }
.mr11 {    margin-right: calc(var(--grid-size) * 11); }
.mr12 {    margin-right: calc(var(--grid-size) * 12); }
.mr13 {    margin-right: calc(var(--grid-size) * 13); }
.mr14 {    margin-right: calc(var(--grid-size) * 14); }
.mr15 {    margin-right: calc(var(--grid-size) * 15); }
.mr16 {    margin-right: calc(var(--grid-size) * 16); }
.mr17 {    margin-right: calc(var(--grid-size) * 17); }
.mr18 {    margin-right: calc(var(--grid-size) * 18); }
.mr19 {    margin-right: calc(var(--grid-size) * 19); }
.mr20 {    margin-right: calc(var(--grid-size) * 20); }
.mr25 {    margin-right: calc(var(--grid-size) * 25); }
.mr30 {    margin-right: calc(var(--grid-size) * 30); }
.mr40 {    margin-right: calc(var(--grid-size) * 40); }
.mr50 {    margin-right: calc(var(--grid-size) * 50); }

.mb0 {    margin-bottom: 0; }
.mb1 {    margin-bottom: calc(var(--grid-size) * 1); }
.mb2 {    margin-bottom: calc(var(--grid-size) * 2); }
.mb3 {    margin-bottom: calc(var(--grid-size) * 3); }
.mb4 {    margin-bottom: calc(var(--grid-size) * 4); }
.mb5 {    margin-bottom: calc(var(--grid-size) * 5); }
.mb6 {    margin-bottom: calc(var(--grid-size) * 6); }
.mb7 {    margin-bottom: calc(var(--grid-size) * 7); }
.mb8 {    margin-bottom: calc(var(--grid-size) * 8); }
.mb9 {    margin-bottom: calc(var(--grid-size) * 9); }
.mb10 {    margin-bottom: calc(var(--grid-size) * 10); }
.mb11 {    margin-bottom: calc(var(--grid-size) * 11); }
.mb12 {    margin-bottom: calc(var(--grid-size) * 12); }
.mb13 {    margin-bottom: calc(var(--grid-size) * 13); }
.mb14 {    margin-bottom: calc(var(--grid-size) * 14); }
.mb15 {    margin-bottom: calc(var(--grid-size) * 15); }
.mb16 {    margin-bottom: calc(var(--grid-size) * 16); }
.mb17 {    margin-bottom: calc(var(--grid-size) * 17); }
.mb18 {    margin-bottom: calc(var(--grid-size) * 18); }
.mb19 {    margin-bottom: calc(var(--grid-size) * 19); }
.mb20 {    margin-bottom: calc(var(--grid-size) * 20); }
.mb25 {    margin-bottom: calc(var(--grid-size) * 25); }
.mb30 {    margin-bottom: calc(var(--grid-size) * 30); }
.mb40 {    margin-bottom: calc(var(--grid-size) * 40); }
.mb50 {    margin-bottom: calc(var(--grid-size) * 50); }

.ml0 {    margin-left: 0; }
.ml1 {    margin-left: calc(var(--grid-size) * 1); }
.ml2 {    margin-left: calc(var(--grid-size) * 2); }
.ml3 {    margin-left: calc(var(--grid-size) * 3); }
.ml4 {    margin-left: calc(var(--grid-size) * 4); }
.ml5 {    margin-left: calc(var(--grid-size) * 5); }
.ml6 {    margin-left: calc(var(--grid-size) * 6); }
.ml7 {    margin-left: calc(var(--grid-size) * 7); }
.ml8 {    margin-left: calc(var(--grid-size) * 8); }
.ml9 {    margin-left: calc(var(--grid-size) * 9); }
.ml10 {    margin-left: calc(var(--grid-size) * 10); }
.ml11 {    margin-left: calc(var(--grid-size) * 11); }
.ml12 {    margin-left: calc(var(--grid-size) * 12); }
.ml13 {    margin-left: calc(var(--grid-size) * 13); }
.ml14 {    margin-left: calc(var(--grid-size) * 14); }
.ml15 {    margin-left: calc(var(--grid-size) * 15); }
.ml16 {    margin-left: calc(var(--grid-size) * 16); }
.ml17 {    margin-left: calc(var(--grid-size) * 17); }
.ml18 {    margin-left: calc(var(--grid-size) * 18); }
.ml19 {    margin-left: calc(var(--grid-size) * 19); }
.ml20 {    margin-left: calc(var(--grid-size) * 20); }
.ml25 {    margin-left: calc(var(--grid-size) * 25); }
.ml30 {    margin-left: calc(var(--grid-size) * 30); }
.ml40 {    margin-left: calc(var(--grid-size) * 40); }
.ml50 {    margin-left: calc(var(--grid-size) * 50); }

.mt0 {    margin-top: 0; }
.mt1 {    margin-top: calc(var(--grid-size) * 1); }
.mt2 {    margin-top: calc(var(--grid-size) * 2); }
.mt3 {    margin-top: calc(var(--grid-size) * 3); }
.mt4 {    margin-top: calc(var(--grid-size) * 4); }
.mt5 {    margin-top: calc(var(--grid-size) * 5); }
.mt6 {    margin-top: calc(var(--grid-size) * 6); }
.mt7 {    margin-top: calc(var(--grid-size) * 7); }
.mt8 {    margin-top: calc(var(--grid-size) * 8); }
.mt9 {    margin-top: calc(var(--grid-size) * 9); }
.mt10 {    margin-top: calc(var(--grid-size) * 10); }
.mt11 {    margin-top: calc(var(--grid-size) * 11); }
.mt12 {    margin-top: calc(var(--grid-size) * 12); }
.mt13 {    margin-top: calc(var(--grid-size) * 13); }
.mt14 {    margin-top: calc(var(--grid-size) * 14); }
.mt15 {    margin-top: calc(var(--grid-size) * 15); }
.mt16 {    margin-top: calc(var(--grid-size) * 16); }
.mt17 {    margin-top: calc(var(--grid-size) * 17); }
.mt18 {    margin-top: calc(var(--grid-size) * 18); }
.mt19 {    margin-top: calc(var(--grid-size) * 19); }
.mt20 {    margin-top: calc(var(--grid-size) * 20); }
.mt25 {    margin-top: calc(var(--grid-size) * 25); }
.mt30 {    margin-top: calc(var(--grid-size) * 30); }
.mt40 {    margin-top: calc(var(--grid-size) * 40); }
.mt50 {    margin-top: calc(var(--grid-size) * 50); }

.na0 {    margin: 0; }
.na1 {    margin: calc(-1 * var(--grid-size) * 1); }
.na2 {    margin: calc(-1 * var(--grid-size) * 2); }
.na3 {    margin: calc(-1 * var(--grid-size) * 3); }
.na4 {    margin: calc(-1 * var(--grid-size) * 4); }
.na5 {    margin: calc(-1 * var(--grid-size) * 5); }
.na6 {    margin: calc(-1 * var(--grid-size) * 6); }
.na7 {    margin: calc(-1 * var(--grid-size) * 7); }
.na8 {    margin: calc(-1 * var(--grid-size) * 8); }
.na9 {    margin: calc(-1 * var(--grid-size) * 9); }
.na10 {    margin: calc(-1 * var(--grid-size) * 10); }
.na11 {    margin: calc(-1 * var(--grid-size) * 11); }
.na12 {    margin: calc(-1 * var(--grid-size) * 12); }
.na13 {    margin: calc(-1 * var(--grid-size) * 13); }
.na14 {    margin: calc(-1 * var(--grid-size) * 14); }
.na15 {    margin: calc(-1 * var(--grid-size) * 15); }
.na16 {    margin: calc(-1 * var(--grid-size) * 16); }
.na17 {    margin: calc(-1 * var(--grid-size) * 17); }
.na18 {    margin: calc(-1 * var(--grid-size) * 18); }
.na19 {    margin: calc(-1 * var(--grid-size) * 19); }
.na20 {    margin: calc(-1 * var(--grid-size) * 20); }
.na25 {    margin: calc(-1 * var(--grid-size) * 25); }
.na30 {    margin: calc(-1 * var(--grid-size) * 30); }
.na40 {    margin: calc(-1 * var(--grid-size) * 40); }
.na50 {    margin: calc(-1 * var(--grid-size) * 50); }

.nr0 {    margin-right: 0; }
.nr1 {    margin-right: calc(-1 * var(--grid-size) * 1); }
.nr2 {    margin-right: calc(-1 * var(--grid-size) * 2); }
.nr3 {    margin-right: calc(-1 * var(--grid-size) * 3); }
.nr4 {    margin-right: calc(-1 * var(--grid-size) * 4); }
.nr5 {    margin-right: calc(-1 * var(--grid-size) * 5); }
.nr6 {    margin-right: calc(-1 * var(--grid-size) * 6); }
.nr7 {    margin-right: calc(-1 * var(--grid-size) * 7); }
.nr8 {    margin-right: calc(-1 * var(--grid-size) * 8); }
.nr9 {    margin-right: calc(-1 * var(--grid-size) * 9); }
.nr10 {    margin-right: calc(-1 * var(--grid-size) * 10); }
.nr11 {    margin-right: calc(-1 * var(--grid-size) * 11); }
.nr12 {    margin-right: calc(-1 * var(--grid-size) * 12); }
.nr13 {    margin-right: calc(-1 * var(--grid-size) * 13); }
.nr14 {    margin-right: calc(-1 * var(--grid-size) * 14); }
.nr15 {    margin-right: calc(-1 * var(--grid-size) * 15); }
.nr16 {    margin-right: calc(-1 * var(--grid-size) * 16); }
.nr17 {    margin-right: calc(-1 * var(--grid-size) * 17); }
.nr18 {    margin-right: calc(-1 * var(--grid-size) * 18); }
.nr19 {    margin-right: calc(-1 * var(--grid-size) * 19); }
.nr20 {    margin-right: calc(-1 * var(--grid-size) * 20); }
.nr25 {    margin-right: calc(-1 * var(--grid-size) * 25); }
.nr30 {    margin-right: calc(-1 * var(--grid-size) * 30); }
.nr40 {    margin-right: calc(-1 * var(--grid-size) * 40); }
.nr50 {    margin-right: calc(-1 * var(--grid-size) * 50); }

.nb0 {    margin-bottom: 0; }
.nb1 {    margin-bottom: calc(-1 * var(--grid-size) * 1); }
.nb2 {    margin-bottom: calc(-1 * var(--grid-size) * 2); }
.nb3 {    margin-bottom: calc(-1 * var(--grid-size) * 3); }
.nb4 {    margin-bottom: calc(-1 * var(--grid-size) * 4); }
.nb5 {    margin-bottom: calc(-1 * var(--grid-size) * 5); }
.nb6 {    margin-bottom: calc(-1 * var(--grid-size) * 6); }
.nb7 {    margin-bottom: calc(-1 * var(--grid-size) * 7); }
.nb8 {    margin-bottom: calc(-1 * var(--grid-size) * 8); }
.nb9 {    margin-bottom: calc(-1 * var(--grid-size) * 9); }
.nb10 {    margin-bottom: calc(-1 * var(--grid-size) * 10); }
.nb11 {    margin-bottom: calc(-1 * var(--grid-size) * 11); }
.nb12 {    margin-bottom: calc(-1 * var(--grid-size) * 12); }
.nb13 {    margin-bottom: calc(-1 * var(--grid-size) * 13); }
.nb14 {    margin-bottom: calc(-1 * var(--grid-size) * 14); }
.nb15 {    margin-bottom: calc(-1 * var(--grid-size) * 15); }
.nb16 {    margin-bottom: calc(-1 * var(--grid-size) * 16); }
.nb17 {    margin-bottom: calc(-1 * var(--grid-size) * 17); }
.nb18 {    margin-bottom: calc(-1 * var(--grid-size) * 18); }
.nb19 {    margin-bottom: calc(-1 * var(--grid-size) * 19); }
.nb20 {    margin-bottom: calc(-1 * var(--grid-size) * 20); }
.nb25 {    margin-bottom: calc(-1 * var(--grid-size) * 25); }
.nb30 {    margin-bottom: calc(-1 * var(--grid-size) * 30); }
.nb40 {    margin-bottom: calc(-1 * var(--grid-size) * 40); }
.nb50 {    margin-bottom: calc(-1 * var(--grid-size) * 50); }

.nl0 {    margin-left: 0; }
.nl1 {    margin-left: calc(-1 * var(--grid-size) * 1); }
.nl2 {    margin-left: calc(-1 * var(--grid-size) * 2); }
.nl3 {    margin-left: calc(-1 * var(--grid-size) * 3); }
.nl4 {    margin-left: calc(-1 * var(--grid-size) * 4); }
.nl5 {    margin-left: calc(-1 * var(--grid-size) * 5); }
.nl6 {    margin-left: calc(-1 * var(--grid-size) * 6); }
.nl7 {    margin-left: calc(-1 * var(--grid-size) * 7); }
.nl8 {    margin-left: calc(-1 * var(--grid-size) * 8); }
.nl9 {    margin-left: calc(-1 * var(--grid-size) * 9); }
.nl10 {    margin-left: calc(-1 * var(--grid-size) * 10); }
.nl11 {    margin-left: calc(-1 * var(--grid-size) * 11); }
.nl12 {    margin-left: calc(-1 * var(--grid-size) * 12); }
.nl13 {    margin-left: calc(-1 * var(--grid-size) * 13); }
.nl14 {    margin-left: calc(-1 * var(--grid-size) * 14); }
.nl15 {    margin-left: calc(-1 * var(--grid-size) * 15); }
.nl16 {    margin-left: calc(-1 * var(--grid-size) * 16); }
.nl17 {    margin-left: calc(-1 * var(--grid-size) * 17); }
.nl18 {    margin-left: calc(-1 * var(--grid-size) * 18); }
.nl19 {    margin-left: calc(-1 * var(--grid-size) * 19); }
.nl20 {    margin-left: calc(-1 * var(--grid-size) * 20); }
.nl25 {    margin-left: calc(-1 * var(--grid-size) * 25); }
.nl30 {    margin-left: calc(-1 * var(--grid-size) * 30); }
.nl40 {    margin-left: calc(-1 * var(--grid-size) * 40); }
.nl50 {    margin-left: calc(-1 * var(--grid-size) * 50); }

.nt0 {    margin-top: 0; }
.nt1 {    margin-top: calc(-1 * var(--grid-size) * 1); }
.nt2 {    margin-top: calc(-1 * var(--grid-size) * 2); }
.nt3 {    margin-top: calc(-1 * var(--grid-size) * 3); }
.nt4 {    margin-top: calc(-1 * var(--grid-size) * 4); }
.nt5 {    margin-top: calc(-1 * var(--grid-size) * 5); }
.nt6 {    margin-top: calc(-1 * var(--grid-size) * 6); }
.nt7 {    margin-top: calc(-1 * var(--grid-size) * 7); }
.nt8 {    margin-top: calc(-1 * var(--grid-size) * 8); }
.nt9 {    margin-top: calc(-1 * var(--grid-size) * 9); }
.nt10 {    margin-top: calc(-1 * var(--grid-size) * 10); }
.nt11 {    margin-top: calc(-1 * var(--grid-size) * 11); }
.nt12 {    margin-top: calc(-1 * var(--grid-size) * 12); }
.nt13 {    margin-top: calc(-1 * var(--grid-size) * 13); }
.nt14 {    margin-top: calc(-1 * var(--grid-size) * 14); }
.nt15 {    margin-top: calc(-1 * var(--grid-size) * 15); }
.nt16 {    margin-top: calc(-1 * var(--grid-size) * 16); }
.nt17 {    margin-top: calc(-1 * var(--grid-size) * 17); }
.nt18 {    margin-top: calc(-1 * var(--grid-size) * 18); }
.nt19 {    margin-top: calc(-1 * var(--grid-size) * 19); }
.nt20 {    margin-top: calc(-1 * var(--grid-size) * 20); }
.nt25 {    margin-top: calc(-1 * var(--grid-size) * 25); }
.nt30 {    margin-top: calc(-1 * var(--grid-size) * 30); }
.nt40 {    margin-top: calc(-1 * var(--grid-size) * 40); }
.nt50 {    margin-top: calc(-1 * var(--grid-size) * 50); }


/* Nudging */
/* ------------------------------------------------------------ */
.nudge-top--1 {
    position: relative;
    top: 1px;
}
.nudge-top--2 {
    position: relative;
    top: 2px;
}
.nudge-top--3 {
    position: relative;
    top: 3px;
}
.nudge-top--4 {
    position: relative;
    top: 4px;
}
.nudge-top--5 {
    position: relative;
    top: 5px;
}
.nudge-top--6 {
    position: relative;
    top: 6px;
}
.nudge-top--7 {
    position: relative;
    top: 7px;
}
.nudge-top--8 {
    position: relative;
    top: 8px;
}
.nudge-top--9 {
    position: relative;
    top: 9px;
}
.nudge-top--10 {
    position: relative;
    top: 10px;
}

.nudge-right--1 {
    position: relative;
    right: 1px;
}
.nudge-right--2 {
    position: relative;
    right: 2px;
}
.nudge-right--3 {
    position: relative;
    right: 3px;
}
.nudge-right--4 {
    position: relative;
    right: 4px;
}
.nudge-right--5 {
    position: relative;
    right: 5px;
}
.nudge-right--6 {
    position: relative;
    right: 6px;
}
.nudge-right--7 {
    position: relative;
    right: 7px;
}
.nudge-right--8 {
    position: relative;
    right: 8px;
}
.nudge-right--9 {
    position: relative;
    right: 9px;
}
.nudge-right--10 {
    position: relative;
    right: 10px;
}

.nudge-bottom--1 {
    position: relative;
    bottom: 1px;
}
.nudge-bottom--2 {
    position: relative;
    bottom: 2px;
}
.nudge-bottom--3 {
    position: relative;
    bottom: 3px;
}
.nudge-bottom--4 {
    position: relative;
    bottom: 4px;
}
.nudge-bottom--5 {
    position: relative;
    bottom: 5px;
}
.nudge-bottom--6 {
    position: relative;
    bottom: 6px;
}
.nudge-bottom--7 {
    position: relative;
    bottom: 7px;
}
.nudge-bottom--8 {
    position: relative;
    bottom: 8px;
}
.nudge-bottom--9 {
    position: relative;
    bottom: 9px;
}
.nudge-bottom--10 {
    position: relative;
    bottom: 10px;
}

.nudge-left--1 {
    position: relative;
    left: 1px;
}
.nudge-left--2 {
    position: relative;
    left: 2px;
}
.nudge-left--3 {
    position: relative;
    left: 3px;
}
.nudge-left--4 {
    position: relative;
    left: 4px;
}
.nudge-left--5 {
    position: relative;
    left: 5px;
}
.nudge-left--6 {
    position: relative;
    left: 6px;
}
.nudge-left--7 {
    position: relative;
    left: 7px;
}
.nudge-left--8 {
    position: relative;
    left: 8px;
}
.nudge-left--9 {
    position: relative;
    left: 9px;
}
.nudge-left--10 {
    position: relative;
    left: 10px;
}

<|start_filename|>core/server/data/importer/importers/data/trusted-domains.js<|end_filename|>
const debug = require('ghost-ignition').debug('importer:clients'),
    Promise = require('bluebird'),
    _ = require('lodash'),
    BaseImporter = require('./base'),
    models = require('../../../../models');

class TrustedDomainsImporter extends BaseImporter {
    constructor(allDataFromFile) {
        super(allDataFromFile, {
            modelName: 'ClientTrustedDomain',
            dataKeyToImport: 'client_trusted_domains',
            requiredExistingData: ['clients'],
            requiredFromFile: ['clients'],
            requiredImportedData: ['clients']
        });

        this.errorConfig = {
            allowDuplicates: false,
            returnDuplicates: true,
            showNotFoundWarning: false
        };
    }

    fetchExisting(modelOptions) {
        return models.ClientTrustedDomain.findAll(_.merge({columns: ['id', 'trusted_domain']}, modelOptions))
            .then((existingData) => {
                this.existingData = existingData.toJSON();
            });
    }

    beforeImport() {
        debug('beforeImport');

        // CASE: compare with existing trusted domains
        this.dataToImport = _.filter(this.dataToImport, (domainToImport) => {
            if (_.find(this.existingData, {trusted_domain: domainToImport.trusted_domain})) {
                return false;
            }

            return true;
        });

        return super.beforeImport();
    }

    replaceIdentifiers(modelOptions, importOptions = {}) {
        debug('replaceIdentifiers');

        if (!importOptions.include || importOptions.include.indexOf(this.dataKeyToImport) === -1) {
            return super.replaceIdentifiers(modelOptions, importOptions);
        }

        const randomClientId = this.requiredExistingData.clients[0].id;

        _.each(this.dataToImport, (domainToImport, index) => {
            let existingClient = _.find(this.requiredFromFile.clients, {id: domainToImport.client_id.toString()});

            // CASE: client is in file, look if it was imported or updated
            if (existingClient) {
                existingClient = _.find(this.requiredImportedData.clients, {slug: existingClient.slug});

                if (existingClient) {
                    this.dataToImport[index].client_id = existingClient.id;
                }
            } else {
                existingClient = _.find(this.requiredExistingData.clients, {id: domainToImport.client_id.toString()});

                if (!existingClient) {
                    this.dataToImport[index].client_id = randomClientId;
                }
            }
        });

        return super.replaceIdentifiers(modelOptions, importOptions);
    }

    generateIdentifier() {
        return Promise.resolve();
    }

    doImport(options, importOptions = {}) {
        debug('doImport', this.dataToImport.length);

        if (!importOptions.include || importOptions.include.indexOf(this.dataKeyToImport) === -1) {
            return Promise.resolve().reflect();
        }

        return super.doImport(options, importOptions);
    }
}

module.exports = TrustedDomainsImporter;


<|start_filename|>core/server/lib/members/static/auth/pages/SigninPage.js<|end_filename|>
import Form from '../components/Form';
import FormHeader from '../components/FormHeader';
import FormHeaderCTA from '../components/FormHeaderCTA';
import FormSubmit from '../components/FormSubmit';
import { IconRightArrow } from '../components/icons';

import EmailInput from '../components/EmailInput';
import PasswordInput from '../components/PasswordInput';

export default ({ error, handleSubmit }) => (
    <div className="flex flex-column items-center">
        <div className="gm-modal-form gm-signin-page">
            <FormHeader title="" error={error} errorText="Wrong email or password">
                <div className="flex justify-between items-baseline">
                    <h1>Log in</h1>
                    <FormHeaderCTA title="Not a member?" label="Sign up" icon={IconRightArrow} hash="#signup" />
                </div>
            </FormHeader>
            <Form onSubmit={handleSubmit}>
                <EmailInput bindTo="email" className="first" />
                <PasswordInput bindTo="password" className="gm-forgot-input last">
                    <a href="#request-password-reset" className="gm-forgot-link">
                        Forgot
                    </a>
                </PasswordInput>
                <FormSubmit label="Log in" />
            </Form>
        </div>
    </div>
);


<|start_filename|>core/server/data/meta/context_object.js<|end_filename|>
var settingsCache = require('../../services/settings/cache'),
    _ = require('lodash');

function getContextObject(data, context) {
    /**
     * If the data object does not contain the requested context, we return the fallback object.
     */
    const blog = {
        cover_image: settingsCache.get('cover_image'),
        twitter: settingsCache.get('twitter'),
        facebook: settingsCache.get('facebook')
    };

    let chosenContext;

    // @TODO: meta layer is very broken, it's really hard to understand what it's doing
    // The problem is that handlebars root object is structured differently. Sometimes the object is flat on data
    // and sometimes the object is part of a key e.g. data.post. This needs to be prepared at the very first stage and not in each helper.
    if ((_.includes(context, 'page') || _.includes(context, 'amp')) && data.post) {
        chosenContext = data.post;
    } else if (_.includes(context, 'post') && data.post) {
        chosenContext = data.post;
    } else if (_.includes(context, 'page') && data.page) {
        chosenContext = data.page;
    } else if (data[context]) {
        // @NOTE: This is confusing as hell. It tries to get data[['author']], which works, but coincidence?
        chosenContext = data[context];
    }

    // Super fallback.
    if (!chosenContext) {
        chosenContext = blog;
    }

    return chosenContext;
}

module.exports = getContextObject;


<|start_filename|>core/server/services/apps/index.js<|end_filename|>
var debug = require('ghost-ignition').debug('services:apps'),
    _ = require('lodash'),
    Promise = require('bluebird'),
    api = require('../../api'),
    common = require('../../lib/common'),
    config = require('../../config'),
    settingsCache = require('../settings/cache'),
    loader = require('./loader'),
    // Internal apps are in config
    internalApps = config.get('apps:internal'),
    // Holds the available apps
    availableApps = {};

function recordLoadedApp(name, loadedApp) {
    // After loading the app, add it to our hash of loaded apps
    availableApps[name] = loadedApp;
    return loadedApp;
}

function saveInstalledApps(installedApps) {
    debug('saving begin');
    var currentInstalledApps = settingsCache.get('installed_apps'),
        // Never save internal apps
        updatedAppsInstalled = _.difference(_.uniq(installedApps.concat(currentInstalledApps)), internalApps);

    if (_.difference(updatedAppsInstalled, currentInstalledApps).length === 0) {
        debug('saving unneeded');
        return new Promise.resolve();
    }

    debug('saving settings');
    return api.settings.edit({
        settings: [{
            key: 'installed_apps',
            value: updatedAppsInstalled
        }]
    }, {context: {internal: true}});
}

module.exports = {
    init: function () {
        debug('init begin');
        var activeApps = settingsCache.get('active_apps'),
            installedApps = settingsCache.get('installed_apps'),
            // Load means either activate, or install and activate
            // We load all Active Apps, and all Internal Apps
            appsToLoad = activeApps.concat(internalApps);

        function loadApp(appName) {
            // If internal or already installed, the app only needs activating
            if (_.includes(internalApps, appName) || _.includes(installedApps, appName)) {
                return loader.activateAppByName(appName).then(function (loadedApp) {
                    return recordLoadedApp(appName, loadedApp);
                });
            }

            // Else first install, then activate the app
            return loader.installAppByName(appName).then(function () {
                return loader.activateAppByName(appName);
            }).then(function (loadedApp) {
                return recordLoadedApp(appName, loadedApp);
            });
        }

        return Promise.map(appsToLoad, loadApp)
            .then(function () {
                // Save our installed apps to settings
                return saveInstalledApps(_.keys(availableApps));
            })
            .catch(function (err) {
                common.logging.error(new common.errors.GhostError({
                    err: err,
                    context: common.i18n.t('errors.apps.appWillNotBeLoaded.error'),
                    help: common.i18n.t('errors.apps.appWillNotBeLoaded.help')
                }));
            });
    },
    availableApps: availableApps
};


<|start_filename|>core/server/api/v2/utils/serializers/output/utils/extra-attrs.js<|end_filename|>
module.exports.forPost = (frame, model, attrs) => {
    const _ = require('lodash');

    if (!frame.options.hasOwnProperty('columns') ||
        (frame.options.columns.includes('excerpt') && frame.options.formats && frame.options.formats.includes('plaintext'))) {
        if (_.isEmpty(attrs.custom_excerpt)) {
            const plaintext = model.get('plaintext');

            if (plaintext) {
                attrs.excerpt = plaintext.substring(0, 500);
            } else {
                attrs.excerpt = null;
            }
        } else {
            attrs.excerpt = attrs.custom_excerpt;
        }
    }
};

// @NOTE: ghost_head & ghost_foot are deprecated, remove in Ghost 3.0
module.exports.forSettings = (attrs, frame) => {
    const _ = require('lodash');

    // @TODO: https://github.com/TryGhost/Ghost/issues/10106
    // @NOTE: Admin & Content API return a different format, need to mappers
    if (_.isArray(attrs)) {
        // CASE: read single setting
        if (frame.original.params && frame.original.params.key) {
            if (frame.original.params.key === 'ghost_head') {
                return;
            }

            if (frame.original.params.key === 'ghost_foot') {
                return;
            }

            if (frame.original.params.key === 'codeinjection_head') {
                attrs[0].key = 'codeinjection_head';
                return;
            }

            if (frame.original.params.key === 'codeinjection_foot') {
                attrs[0].key = 'codeinjection_foot';
                return;
            }
        }

        // CASE: edit
        if (frame.original.body && frame.original.body.settings) {
            frame.original.body.settings.forEach((setting) => {
                if (setting.key === 'codeinjection_head') {
                    const target = _.find(attrs, {key: 'ghost_head'});
                    target.key = 'codeinjection_head';
                } else if (setting.key === 'codeinjection_foot') {
                    const target = _.find(attrs, {key: 'ghost_foot'});
                    target.key = 'codeinjection_foot';
                }
            });

            return;
        }

        // CASE: browse all settings, add extra keys and keep deprecated
        const ghostHead = _.cloneDeep(_.find(attrs, {key: 'ghost_head'}));
        const ghostFoot = _.cloneDeep(_.find(attrs, {key: 'ghost_foot'}));

        if (ghostHead) {
            ghostHead.key = 'codeinjection_head';
            attrs.push(ghostHead);
        }

        if (ghostFoot) {
            ghostFoot.key = 'codeinjection_foot';
            attrs.push(ghostFoot);
        }
    } else {
        attrs.codeinjection_head = attrs.ghost_head;
        attrs.codeinjection_foot = attrs.ghost_foot;
    }
};


<|start_filename|>core/server/adapters/storage/utils.js<|end_filename|>
const urlService = require('../../services/url');

/**
 * @TODO: move `events.js` to here - e.g. storageUtils.getStorage
 */

/**
 * Sanitizes a given URL or path for an image to be readable by the local file storage
 * as storage needs the path without `/content/images/` prefix
 * Always returns {string} url
 * @param {string} imagePath
 * @returns {string} imagePath
 * @description Takes a url or filepath and returns a filepath with is readable
 * for the local file storage.
 */
exports.getLocalFileStoragePath = function getLocalFileStoragePath(imagePath) {
    // The '/' in urlJoin is necessary to add the '/' to `content/images`, if no subdirectory is setup
    const urlRegExp = new RegExp(`^${urlService.utils.urlJoin(
            urlService.utils.urlFor('home', true),
            urlService.utils.getSubdir(),
            '/',
            urlService.utils.STATIC_IMAGE_URL_PREFIX)}`
        ),
        filePathRegExp = new RegExp(`^${urlService.utils.urlJoin(
            urlService.utils.getSubdir(),
            '/',
            urlService.utils.STATIC_IMAGE_URL_PREFIX)}`
        );

    if (imagePath.match(urlRegExp)) {
        return imagePath.replace(urlRegExp, '');
    } else if (imagePath.match(filePathRegExp)) {
        return imagePath.replace(filePathRegExp, '');
    } else {
        return imagePath;
    }
};

/**
 * @description compares the imagePath with a regex that reflects our local file storage
 * @param {String} imagePath as URL or filepath
 * @returns {Boolean}
 */

exports.isLocalImage = function isLocalImage(imagePath) {
    const localImagePath = this.getLocalFileStoragePath(imagePath);

    if (localImagePath !== imagePath) {
        return true;
    } else {
        return false;
    }
};


<|start_filename|>core/server/lib/social/index.js<|end_filename|>
module.exports = {
    get urls() {
        return require('./urls');
    }
};


<|start_filename|>core/server/data/importer/importers/data/clients.js<|end_filename|>
const debug = require('ghost-ignition').debug('importer:clients'),
    Promise = require('bluebird'),
    _ = require('lodash'),
    BaseImporter = require('./base'),
    models = require('../../../../models');

class ClientsImporter extends BaseImporter {
    constructor(allDataFromFile) {
        super(allDataFromFile, {
            modelName: 'Client',
            dataKeyToImport: 'clients'
        });

        this.errorConfig = {
            allowDuplicates: false,
            returnDuplicates: true,
            showNotFoundWarning: false
        };
    }

    fetchExisting(modelOptions) {
        return models.Client.findAll(_.merge({columns: ['id', 'slug']}, modelOptions))
            .then((existingData) => {
                this.existingData = existingData.toJSON();
            });
    }

    beforeImport() {
        debug('beforeImport');
        return super.beforeImport();
    }

    doImport(options, importOptions = {}) {
        debug('doImport', this.dataToImport.length);

        let ops = [];

        if (!importOptions.include || importOptions.include.indexOf(this.dataKeyToImport) === -1) {
            return Promise.resolve().reflect();
        }

        _.each(this.dataToImport, (obj) => {
            ops.push(models[this.modelName].findOne({slug: obj.slug}, options)
                .then((client) => {
                    if (client) {
                        return models[this.modelName]
                            .edit(_.omit(obj, 'id'), Object.assign({id: client.id}, options))
                            .then((importedModel) => {
                                obj.model = {
                                    id: importedModel.id
                                };

                                if (importOptions.returnImportedData) {
                                    this.importedDataToReturn.push(importedModel.toJSON());
                                }

                                // for identifier lookup
                                this.importedData.push({
                                    id: importedModel.id,
                                    slug: importedModel.get('slug'),
                                    originalSlug: obj.slug
                                });

                                return importedModel;
                            })
                            .catch((err) => {
                                return this.handleError(err, obj);
                            });
                    }

                    // @NOTE: name is also unique
                    return models[this.modelName].findOne({name: obj.name}, options);
                })
                .then((client) => {
                    if (client) {
                        obj.name = `${obj.name}-1`;
                    }

                    return models[this.modelName].add(obj, options)
                        .then((importedModel) => {
                            obj.model = {
                                id: importedModel.id
                            };

                            if (importOptions.returnImportedData) {
                                this.importedDataToReturn.push(importedModel.toJSON());
                            }

                            // for identifier lookup
                            this.importedData.push({
                                id: importedModel.id,
                                slug: importedModel.get('slug'),
                                originalSlug: obj.slug
                            });

                            return importedModel;
                        })
                        .catch((err) => {
                            return this.handleError(err, obj);
                        });
                }).reflect());
        });

        return Promise.all(ops);
    }
}

module.exports = ClientsImporter;


<|start_filename|>core/server/api/v0.1/db.js<|end_filename|>
// # DB API
// API for DB operations
const Promise = require('bluebird'),
    _ = require('lodash'),
    pipeline = require('../../lib/promise/pipeline'),
    localUtils = require('./utils'),
    exporter = require('../../data/exporter'),
    importer = require('../../data/importer'),
    backupDatabase = require('../../data/db/backup'),
    models = require('../../models'),
    common = require('../../lib/common'),
    docName = 'db';

let db;

/**
 * ## DB API Methods
 *
 * **See:** [API Methods](constants.js.html#api%20methods)
 */
db = {
    /**
     * ### Archive Content
     * Generate the JSON to export
     *
     * @public
     * @returns {Promise} Ghost Export JSON format
     */
    backupContent(options) {
        let tasks;

        options = options || {};

        function jsonResponse(filename) {
            return {db: [{filename: filename}]};
        }

        tasks = [
            localUtils.convertOptions(exporter.EXCLUDED_TABLES, null, {forModel: false}),
            backupDatabase,
            jsonResponse
        ];

        return pipeline(tasks, options);
    },
    /**
     * ### Export Content
     * Generate the JSON to export
     *
     * @public
     * @param {{context}} options
     * @returns {Promise} Ghost Export JSON format
     */
    exportContent(options) {
        let tasks;

        options = options || {};

        // Export data, otherwise send error 500
        function exportContent(options) {
            return exporter.doExport({include: options.include}).then((exportedData) => {
                return {
                    db: [exportedData]
                };
            }).catch((err) => {
                return Promise.reject(new common.errors.GhostError({err: err}));
            });
        }

        tasks = [
            localUtils.handlePermissions(docName, 'exportContent'),
            localUtils.convertOptions(exporter.EXCLUDED_TABLES, null, {forModel: false}),
            exportContent
        ];

        return pipeline(tasks, options);
    },
    /**
     * ### Import Content
     * Import posts, tags etc from a JSON blob
     *
     * @public
     * @param {{context}} options
     * @returns {Promise} Success
     */
    importContent(options) {
        let tasks;
        options = options || {};

        function importContent(options) {
            return importer.importFromFile(_.omit(options, 'include'), {include: options.include})
                // NOTE: response can contain 2 objects if images are imported
                .then((response) => {
                    return {
                        db: [],
                        problems: response.length === 2 ? response[1].problems : response[0].problems
                    };
                });
        }

        tasks = [
            localUtils.handlePermissions(docName, 'importContent'),
            localUtils.convertOptions(exporter.EXCLUDED_TABLES, null, {forModel: false}),
            importContent
        ];

        return pipeline(tasks, options);
    },
    /**
     * ### Delete All Content
     * Remove all posts and tags
     *
     * @public
     * @param {{context}} options
     * @returns {Promise} Success
     */
    deleteAllContent(options) {
        let tasks;
        const queryOpts = {columns: 'id', context: {internal: true}, destroyAll: true};

        options = options || {};

        /**
         * @NOTE:
         * We fetch all posts with `columns:id` to increase the speed of this endpoint.
         * And if you trigger `post.destroy(..)`, this will trigger bookshelf and model events.
         * But we only have to `id` available in the model. This won't work, because:
         *   - model layer can't trigger event e.g. `post.page` to trigger `post|page.unpublished`.
         *   - `onDestroyed` or `onDestroying` can contain custom logic
         */
        function deleteContent() {
            return models.Base.transaction((transacting) => {
                queryOpts.transacting = transacting;

                return models.Post.findAll(queryOpts)
                    .then((response) => {
                        return Promise.map(response.models, (post) => {
                            return models.Post.destroy(Object.assign({id: post.id}, queryOpts));
                        }, {concurrency: 100});
                    })
                    .then(() => {
                        return models.Tag.findAll(queryOpts);
                    })
                    .then((response) => {
                        return Promise.map(response.models, (tag) => {
                            return models.Tag.destroy(Object.assign({id: tag.id}, queryOpts));
                        }, {concurrency: 100});
                    })
                    .return({db: []})
                    .catch((err) => {
                        throw new common.errors.GhostError({
                            err: err
                        });
                    });
            });
        }

        tasks = [
            localUtils.handlePermissions(docName, 'deleteAllContent'),
            backupDatabase,
            deleteContent
        ];

        return pipeline(tasks, options);
    }
};

module.exports = db;


<|start_filename|>core/server/lib/members/static/auth/components/FormSubmit.js<|end_filename|>
export default ({onClick, label}) => (
    <div className="mt7">
        <button type="submit" className="gm-btn-blue" onClick={onClick}>
            { label }
        </button>
    </div>
);


<|start_filename|>core/server/web/shared/middlewares/api/index.js<|end_filename|>
module.exports = {
    get cors() {
        return require('./cors');
    },

    get spamPrevention() {
        return require('./spam-prevention');
    },

    get versionMatch() {
        return require('./version-match');
    }
};


<|start_filename|>core/server/lib/members/static/auth/layer0.js<|end_filename|>
/* globals window */
module.exports = function layer0(frame) {
    var getuid = (function (i) {
        return function () {
            return i += 1;
        };
    })(1);
    var origin = new URL(frame.getAttribute('src')).origin;
    var handlers = {};
    var listener = function () {};

    window.addEventListener('message', function (event) {
        if (event.origin !== origin) {
            return;
        }
        if (!event.data || !event.data.uid) {
            if (event.data.event) {
                return listener(event.data);
            }
            return;
        }
        var handler = handlers[event.data.uid];
        if (!handler) {
            return;
        }
        delete handlers[event.data.uid];
        handler(event.data.error, event.data.data);
    });

    function call(method, options, cb) {
        var uid = getuid();
        var data = {uid, method, options};
        handlers[uid] = cb;
        frame.contentWindow.postMessage(data, origin);
    }

    function listen(fn) {
        listener = fn;
    }

    return {call, listen};
};


<|start_filename|>core/server/lib/members/static/auth/pages/RequestPasswordResetPage.js<|end_filename|>
import FormHeader from '../components/FormHeader';
import EmailInput from '../components/EmailInput';
import FormSubmit from '../components/FormSubmit';

import Form from '../components/Form';

export default ({ error, handleClose, handleSubmit }) => (
    <div className="gm-modal-form gm-reset-pwd-page">
        <FormHeader title="Reset password" error={error} errorText="Unable to send email" />
        <Form bindTo="request-password-reset" onSubmit={handleSubmit}>
            <EmailInput bindTo="email" className="single" />
            <FormSubmit label="Send reset password instructions" />
            <div class="flex justify-center mt5">
                <a href="#signin">Cancel</a>
            </div>
        </Form>
    </div>
);


<|start_filename|>core/server/lib/mobiledoc/atoms/index.js<|end_filename|>
const softReturn = require('./soft-return');

module.exports = [softReturn];


<|start_filename|>core/server/api/v2/utils/serializers/output/utils/members.js<|end_filename|>
const labs = require('../../../../../../services/labs');
const membersService = require('../../../../../../services/members');
const MEMBER_TAG = '#members';
const PERMIT_CONTENT = false;
const BLOCK_CONTENT = true;

// Checks if request should hide memnbers only content
function hideMembersOnlyContent(attrs, frame) {
    const membersEnabled = labs.isSet('members');
    if (!membersEnabled) {
        return PERMIT_CONTENT;
    }

    const postHasMemberTag = attrs.tags && attrs.tags.find((tag) => {
        return (tag.name === MEMBER_TAG);
    });
    const requestFromMember = frame.original.context.member;
    if (!postHasMemberTag) {
        return PERMIT_CONTENT;
    }
    if (!requestFromMember) {
        return BLOCK_CONTENT;
    }

    const memberHasPlan = !!(frame.original.context.member.plans || []).length;
    if (!membersService.api.isPaymentConfigured()) {
        return PERMIT_CONTENT;
    }
    if (memberHasPlan) {
        return PERMIT_CONTENT;
    }
    return BLOCK_CONTENT;
}

const forPost = (attrs, frame) => {
    const hideFormatsData = hideMembersOnlyContent(attrs, frame);
    if (hideFormatsData) {
        ['plaintext', 'html'].forEach((field) => {
            attrs[field] = '';
        });
    }
    if (labs.isSet('members')) {
        // CASE: Members always adds tags, remove if the user didn't originally ask for them
        const origQueryOrOptions = frame.original.query || frame.original.options || {};
        const origInclude = origQueryOrOptions.include;

        if (!origInclude || !origInclude.includes('tags')) {
            delete attrs.tags;
            attrs.primary_tag = null;
        }
    }

    return attrs;
};

module.exports.forPost = forPost;


<|start_filename|>core/server/index.js<|end_filename|>
/**
 * make sure overrides get's called first!
 * - keeping the overrides import here works for installing Ghost as npm!
 *
 * the call order is the following:
 * - root index requires core module
 * - core index requires server
 * - overrides is the first package to load
 */
require('./overrides');

const debug = require('ghost-ignition').debug('boot:init');
const Promise = require('bluebird');
const config = require('./config');
const common = require('./lib/common');
const migrator = require('./data/db/migrator');
const urlService = require('./services/url');
let parentApp;

function initialiseServices() {
    // CASE: When Ghost is ready with bootstrapping (db migrations etc.), we can trigger the router creation.
    //       Reason is that the routers access the routes.yaml, which shouldn't and doesn't have to be validated to
    //       start Ghost in maintenance mode.
    const routing = require('./services/routing');
    routing.bootstrap.start();

    const permissions = require('./services/permissions'),
        auth = require('./services/auth'),
        apps = require('./services/apps'),
        xmlrpc = require('./services/xmlrpc'),
        slack = require('./services/slack'),
        webhooks = require('./services/webhooks'),
        scheduling = require('./adapters/scheduling');

    debug('`initialiseServices` Start...');

    return Promise.join(
        // Initialize the permissions actions and objects
        permissions.init(),
        xmlrpc.listen(),
        slack.listen(),
        webhooks.listen(),
        apps.init(),
        scheduling.init({
            schedulerUrl: config.get('scheduling').schedulerUrl,
            active: config.get('scheduling').active,
            apiUrl: urlService.utils.urlFor('api', {version: 'v0.1', versionType: 'content'}, true),
            internalPath: config.get('paths').internalSchedulingPath,
            contentPath: config.getContentPath('scheduling')
        })
    ).then(function () {
        debug('XMLRPC, Slack, Webhooks, Apps, Scheduling, Permissions done');

        // Initialise analytics events
        if (config.get('segment:key')) {
            require('./analytics-events').init();
        }
    }).then(function () {
        parentApp.use(auth.init());
        debug('Auth done');

        debug('...`initialiseServices` End');
    });
}

/**
 * - initialise models
 * - initialise i18n
 * - load all settings into settings cache (almost every component makes use of this cache)
 * - load active theme
 * - create our express apps (site, admin, api)
 * - start the ghost server
 * - enable maintenance mode if migrations are missing
 */
const minimalRequiredSetupToStartGhost = (dbState) => {
    const settings = require('./services/settings');
    const models = require('./models');
    const themes = require('./services/themes');
    const GhostServer = require('./ghost-server');

    let ghostServer;

    // Initialize Ghost core internationalization
    common.i18n.init();
    debug('Default i18n done for core');

    models.init();
    debug('Models done');

    return settings.init()
        .then(() => {
            debug('Settings done');
            return themes.init();
        })
        .then(() => {
            debug('Themes done');

            parentApp = require('./web/parent-app')();
            debug('Express Apps done');

            return new GhostServer(parentApp);
        })
        .then((_ghostServer) => {
            ghostServer = _ghostServer;

            // CASE: all good or db was just initialised
            if (dbState === 1 || dbState === 2) {
                common.events.emit('db.ready');

                return initialiseServices()
                    .then(() => {
                        return ghostServer;
                    });
            }

            // CASE: migrations required, put blog into maintenance mode
            if (dbState === 4) {
                common.logging.info('Blog is in maintenance mode.');

                config.set('maintenance:enabled', true);

                migrator.migrate()
                    .then(() => {
                        common.events.emit('db.ready');
                        return initialiseServices();
                    })
                    .then(() => {
                        config.set('maintenance:enabled', false);
                        common.logging.info('Blog is out of maintenance mode.');
                        return GhostServer.announceServerStart();
                    })
                    .catch((err) => {
                        return GhostServer.announceServerStopped(err)
                            .finally(() => {
                                common.logging.error(err);
                                setTimeout(() => {
                                    process.exit(-1);
                                }, 100);
                            });
                    });

                return ghostServer;
            }
        });
};

/**
 * Connect to database.
 * Check db state.
 */
const isDatabaseInitialisationRequired = () => {
    const db = require('./data/db/connection');
    let dbState;

    return migrator.getState()
        .then((state) => {
            dbState = state;

            // CASE: db initialisation required, wait till finished
            if (dbState === 2) {
                return migrator.dbInit();
            }

            // CASE: is db incompatible? e.g. you can't connect a 0.11 database with Ghost 1.0 or 2.0
            if (dbState === 3) {
                return migrator.isDbCompatible(db)
                    .then(() => {
                        dbState = 2;
                        return migrator.dbInit();
                    });
            }
        })
        .then(() => {
            return minimalRequiredSetupToStartGhost(dbState);
        });
};

module.exports = isDatabaseInitialisationRequired;


<|start_filename|>core/server/lib/image/image-size.js<|end_filename|>
const debug = require('ghost-ignition').debug('utils:image-size');
const sizeOf = require('image-size');
const url = require('url');
const Promise = require('bluebird');
const _ = require('lodash');
const request = require('../request');
const urlService = require('../../services/url');
const common = require('../common');
const config = require('../../config');
const storage = require('../../adapters/storage');
const storageUtils = require('../../adapters/storage/utils');
let getImageSizeFromUrl;
let getImageSizeFromStoragePath;
let getImageSizeFromPath;

/**
 * @description processes the Buffer result of an image file
 * @param {Object} options
 * @returns {Object} dimensions
 */
function fetchDimensionsFromBuffer(options) {
    const buffer = options.buffer;
    const imagePath = options.imagePath;
    const imageObject = {};
    let dimensions;

    imageObject.url = imagePath;

    try {
        // Using the Buffer rather than an URL requires to use sizeOf synchronously.
        // See https://github.com/image-size/image-size#asynchronous
        dimensions = sizeOf(buffer);

        // CASE: `.ico` files might have multiple images and therefore multiple sizes.
        // We return the largest size found (image-size default is the first size found)
        if (dimensions.images) {
            dimensions.width = _.maxBy(dimensions.images, (w) => {
                return w.width;
            }).width;
            dimensions.height = _.maxBy(dimensions.images, (h) => {
                return h.height;
            }).height;
        }

        imageObject.width = dimensions.width;
        imageObject.height = dimensions.height;

        return Promise.resolve(imageObject);
    } catch (err) {
        return Promise.reject(new common.errors.InternalServerError({
            code: 'IMAGE_SIZE',
            err: err,
            context: imagePath
        }));
    }
}

// Supported formats of https://github.com/image-size/image-size:
// BMP, GIF, JPEG, PNG, PSD, TIFF, WebP, SVG, ICO
// ***
// Takes the url of the image and an optional timeout
// getImageSizeFromUrl returns an Object like this
// {
//     height: 50,
//     url: 'http://myblog.com/images/cat.jpg',
//     width: 50
// };
// if the dimensions can be fetched, and rejects with error, if not.
// ***
// In case we get a locally stored image, which is checked withing the `isLocalImage`
// function we switch to read the image from the local file storage with `getImageSizeFromStoragePath`.
// In case the image is not stored locally and is missing the protocol (like //www.gravatar.com/andsoon),
// we add the protocol and use urlFor() to get the absolute URL.
// If the request fails or image-size is not able to read the file, we reject with error.

/**
 * @description read image dimensions from URL
 * @param {String} imagePath as URL
 * @returns {Promise<Object>} imageObject or error
 */
getImageSizeFromUrl = (imagePath) => {
    let requestOptions;
    let parsedUrl;
    let timeout = config.get('times:getImageSizeTimeoutInMS') || 10000;

    if (storageUtils.isLocalImage(imagePath)) {
        // don't make a request for a locally stored image
        return getImageSizeFromStoragePath(imagePath);
    }

    // CASE: pre 1.0 users were able to use an asset path for their blog logo
    if (imagePath.match(/^\/assets/)) {
        imagePath = urlService.utils.urlJoin(urlService.utils.urlFor('home', true), urlService.utils.getSubdir(), '/', imagePath);
    }

    parsedUrl = url.parse(imagePath);

    // check if we got an url without any protocol
    if (!parsedUrl.protocol) {
        // CASE: our gravatar URLs start with '//' and we need to add 'http:'
        // to make the request work
        imagePath = 'http:' + imagePath;
    }

    debug('requested imagePath:', imagePath);
    requestOptions = {
        headers: {
            'User-Agent': 'Mozilla/5.0 Safari/537.36'
        },
        timeout: timeout,
        encoding: null
    };

    return request(
        imagePath,
        requestOptions
    ).then((response) => {
        debug('Image fetched (URL):', imagePath);

        return fetchDimensionsFromBuffer({
            buffer: response.body,
            // we need to return the URL that's accessible for network requests as this imagePath
            // value will be used as the URL for structured data
            imagePath: parsedUrl.href
        });
    }).catch({code: 'URL_MISSING_INVALID'}, (err) => {
        return Promise.reject(new common.errors.InternalServerError({
            message: err.message,
            code: 'IMAGE_SIZE_URL',
            statusCode: err.statusCode,
            context: err.url || imagePath
        }));
    }).catch({code: 'ETIMEDOUT'}, {statusCode: 408}, (err) => {
        return Promise.reject(new common.errors.InternalServerError({
            message: 'Request timed out.',
            code: 'IMAGE_SIZE_URL',
            statusCode: err.statusCode,
            context: err.url || imagePath
        }));
    }).catch({code: 'ENOENT'}, {statusCode: 404}, (err) => {
        return Promise.reject(new common.errors.NotFoundError({
            message: 'Image not found.',
            code: 'IMAGE_SIZE_URL',
            statusCode: err.statusCode,
            context: err.url || imagePath
        }));
    }).catch(function (err) {
        if (common.errors.utils.isIgnitionError(err)) {
            return Promise.reject(err);
        }

        return Promise.reject(new common.errors.InternalServerError({
            message: 'Unknown Request error.',
            code: 'IMAGE_SIZE_URL',
            statusCode: err.statusCode,
            context: err.url || imagePath,
            err: err
        }));
    });
};

// Supported formats of https://github.com/image-size/image-size:
// BMP, GIF, JPEG, PNG, PSD, TIFF, WebP, SVG, ICO
// ***
// Takes the url or filepath of the image and reads it form the local
// file storage.
// getImageSizeFromStoragePath returns an Object like this
// {
//     height: 50,
//     url: 'http://myblog.com/images/cat.jpg',
//     width: 50
// };
// if the image is found and dimensions can be fetched, and rejects with error, if not.
/**
 * @description read image dimensions from local file storage
 * @param {String} imagePath
 * @returns {object} imageObject or error
 */
getImageSizeFromStoragePath = (imagePath) => {
    let filePath;

    imagePath = urlService.utils.urlFor('image', {image: imagePath}, true);

    // get the storage readable filePath
    filePath = storageUtils.getLocalFileStoragePath(imagePath);

    return storage.getStorage()
        .read({path: filePath})
        .then((buf) => {
            debug('Image fetched (storage):', filePath);

            return fetchDimensionsFromBuffer({
                buffer: buf,
                // we need to return the URL that's accessible for network requests as this imagePath
                // value will be used as the URL for structured data
                imagePath: imagePath
            });
        }).catch({code: 'ENOENT'}, (err) => {
            return Promise.reject(new common.errors.NotFoundError({
                message: err.message,
                code: 'IMAGE_SIZE_STORAGE',
                err: err,
                context: filePath,
                errorDetails: {
                    originalPath: imagePath,
                    reqFilePath: filePath
                }
            }));
        }).catch((err) => {
            if (common.errors.utils.isIgnitionError(err)) {
                return Promise.reject(err);
            }

            return Promise.reject(new common.errors.InternalServerError({
                message: err.message,
                code: 'IMAGE_SIZE_STORAGE',
                err: err,
                context: filePath,
                errorDetails: {
                    originalPath: imagePath,
                    reqFilePath: filePath
                }
            }));
        });
};

/**
 * Supported formats of https://github.com/image-size/image-size:
 * BMP, GIF, JPEG, PNG, PSD, TIFF, WebP, SVG, ICO
 * Get dimensions for a file from its real file storage path
 * Always returns {object} getImageDimensions
 * @param {string} path
 * @returns {Promise<Object>} getImageDimensions
 * @description Takes a file path and returns width and height.
 */
getImageSizeFromPath = (path) => {
    return new Promise(function getSize(resolve, reject) {
        let dimensions;

        try {
            dimensions = sizeOf(path);

            if (dimensions.images) {
                dimensions.width = _.maxBy(dimensions.images, (w) => {
                    return w.width;
                }).width;
                dimensions.height = _.maxBy(dimensions.images, (h) => {
                    return h.height;
                }).height;
            }

            return resolve({
                width: dimensions.width,
                height: dimensions.height
            });
        } catch (err) {
            return reject(new common.errors.ValidationError({
                message: common.i18n.t('errors.utils.images.invalidDimensions', {
                    file: path,
                    error: err.message
                })
            }));
        }
    });
};

module.exports.getImageSizeFromUrl = getImageSizeFromUrl;
module.exports.getImageSizeFromStoragePath = getImageSizeFromStoragePath;
module.exports.getImageSizeFromPath = getImageSizeFromPath;


<|start_filename|>core/server/web/shared/middlewares/validation/index.js<|end_filename|>
module.exports = {
    get upload() {
        return require('./upload');
    },

    get blogIcon() {
        return require('./blog-icon');
    },

    get profileImage() {
        return require('./profile-image');
    }
};


<|start_filename|>core/server/lib/members/static/auth/preact.config.js<|end_filename|>
export default function (config, env, helpers) {
    const postcssLoader = helpers.getLoadersByName(config, 'postcss-loader');
    const cssLoader = helpers.getLoadersByName(config, 'css-loader');
    postcssLoader.forEach(({ loader }) => (delete loader.options));
    cssLoader.forEach(({ loader }) => (delete loader.options));

    helpers.getRulesByMatchingFile(config, '*.css').forEach(({ rule }) => {
        let filter = (rule.include || rule.exclude || []);
        let newFilter = filter[0].replace('/components', '/styles');
        filter.push(newFilter);
    });

    if (env.production) {
        config.output.publicPath = 'static/';
    } else {
        config.output.publicPath = 'http://localhost:8080/';
    }
    config.devServer = {
        quiet: true,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "*",
            "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
        }
    }
}


<|start_filename|>core/server/api/v2/utils/serializers/output/config.js<|end_filename|>
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:output:config');

module.exports = {
    all(data, apiConfig, frame) {
        frame.response = {
            config: data
        };

        debug(frame.response);
    }
};


<|start_filename|>core/server/lib/members/static/auth/index.js<|end_filename|>
import './styles/members.css';
import { Component } from 'preact';

import MembersProvider from './components/MembersProvider';
import Modal from './components/Modal';

export default class App extends Component {
    constructor() {
        super();
        const apiUrl = window.location.href.substring(0, window.location.href.indexOf('/members/auth'));

        this.state = {
            apiUrl
        };
    }

    render() {
        return (
            <MembersProvider apiUrl={ this.state.apiUrl }>
                 <Modal />
            </MembersProvider>
        );
    }
}


<|start_filename|>core/server/services/auth/index.js<|end_filename|>
module.exports = {
    get authorize() {
        return require('./authorize');
    },

    get authenticate() {
        return require('./authenticate');
    },

    get session() {
        return require('./session');
    },
    /*
     * TODO: Get rid of these when v0.1 is gone
     */
    get init() {
        return (options) => {
            require('./oauth').init(options);
            return require('./passport').init(options);
        };
    },
    get oauth() {
        return require('./oauth');
    }
};


<|start_filename|>core/server/lib/members/static/auth/components/Form.js<|end_filename|>
import { Component } from 'preact';

const states = {};

export default class Form extends Component {

    constructor(props) {
        super(props);
        const includeData = props.includeData || {};

        if (props.bindTo) {
            if (states[props.bindTo]) {
                this.state = states[props.bindTo]
                this.state.data = { ...this.state.data, ...includeData };
            } else {
                states[props.bindTo] = this.state = {
                    submitted: false,
                    data: {...includeData}
                }
            }
        } else {
            this.state = {
                submitted: false,
                data: {...includeData}
            }
        }
    }

    wrapChildren(children, data, onInput = () => {}) {
        return children.map(child => {
            const { bindTo } = child.attributes || {};
            if (bindTo) {
                child.attributes.value = data[bindTo];
                child.attributes.onInput = (e) => {
                    // This is a hack
                    // Preact keeps copy of the child attributes to know whether to rerender
                    // The state change below will for a check, and the old attributes will be reused
                    child.attributes.error = false;
                    this.setState({
                        submitted: false,
                        data: Object.assign({}, this.state.data, {
                            [bindTo]: e.target.value
                        })
                    });
                }

                if (this.state.submitted && !data[bindTo]) {
                    child.attributes.error = true;
                }
            }
            return child;
        })
    }

    wrapSubmit(onSubmit = () => {}, children, data) {
        return (e) => {
            e.preventDefault();

            const requiredFields = children.map(c => c.attributes.bindTo).filter(x => !!x)
            if (!requiredFields.some(x => !data[x])) {
                onSubmit(this.state.data)
            }
            this.setState({
                submitted: true
            });
        }
    }

    render({bindTo, children, onInput, onSubmit}, state) {
        if (bindTo) {
            states[bindTo] = state;
        }
        const data = state.data;
        return (
            <div className="flex flex-column mt7">
                <form className="gm-signup-form" onSubmit={this.wrapSubmit(onSubmit, children, data)} noValidate>
                    { this.wrapChildren(children, data, onInput) }
                </form>
            </div>
        );
    }
}


<|start_filename|>core/server/api/shared/utils/options.js<|end_filename|>
const _ = require('lodash');

const trimAndLowerCase = (params) => {
    params = params || '';

    if (_.isString(params)) {
        params = params.split(',');
    }

    return params.map((item) => {
        return item.trim().toLowerCase();
    });
};

module.exports.trimAndLowerCase = trimAndLowerCase;


<|start_filename|>core/server/lib/members/static/auth/pages/ResetPasswordPage.js<|end_filename|>
import FormHeader from '../components/FormHeader';
import PasswordInput from '../components/PasswordInput';
import FormSubmit from '../components/FormSubmit';
import Form from '../components/Form';

const getTokenData = frameLocation => {
    const params = new URLSearchParams(frameLocation.query);
    const token = params.get('token') || '';
    return { token };

};

export default ({ error, frameLocation, handleSubmit }) => (
    <div className="gm-modal-form">
        <FormHeader title="Reset password" error={error} errorText="Unable to reset password" />
        <Form includeData={getTokenData(frameLocation)} onSubmit={handleSubmit}>
            <PasswordInput bindTo="password" className="single" />
            <FormSubmit label="Set password" />
        </Form>
    </div>
);


<|start_filename|>core/server/services/auth/session/index.js<|end_filename|>
module.exports = {
    // @TODO: expose files/units and not functions of units
    get createSession() {
        return require('./middleware').createSession;
    },

    get destroySession() {
        return require('./middleware').destroySession;
    },

    get authenticate() {
        return require('./middleware').authenticate;
    }
};


<|start_filename|>core/server/api/v2/site.js<|end_filename|>
const ghostVersion = require('../../lib/ghost-version');
const settingsCache = require('../../services/settings/cache');
const urlService = require('../../services/url');

const site = {
    docName: 'site',

    read: {
        permissions: false,
        query() {
            return {
                title: settingsCache.get('title'),
                url: urlService.utils.urlFor('home', true),
                version: ghostVersion.safe
            };
        }
    }
};

module.exports = site;


<|start_filename|>core/server/lib/security/string.js<|end_filename|>
const unidecode = require('unidecode'),
    _ = require('lodash');

module.exports.safe = function safe(string, options) {
    options = options || {};

    if (string === null) {
        string = '';
    }

    // Handle the £ symbol separately, since it needs to be removed before the unicode conversion.
    string = string.replace(/£/g, '-');

    // Remove non ascii characters
    string = unidecode(string);

    // Replace URL reserved chars: `@:/?#[]!$&()*+,;=` as well as `\%<>|^~£"{}` and \`
    string = string.replace(/(\s|\.|@|:|\/|\?|#|\[|\]|!|\$|&|\(|\)|\*|\+|,|;|=|\\|%|<|>|\||\^|~|"|\{|\}|`|–|—)/g, '-')
    // Remove apostrophes
        .replace(/'/g, '')
        // Make the whole thing lowercase
        .toLowerCase();

    // We do not need to make the following changes when importing data
    if (!_.has(options, 'importing') || !options.importing) {
        // Convert 2 or more dashes into a single dash
        string = string.replace(/-+/g, '-')
        // Remove trailing dash
            .replace(/-$/, '')
            // Remove any dashes at the beginning
            .replace(/^-/, '');
    }

    // Handle whitespace at the beginning or end.
    string = string.trim();

    return string;
};


<|start_filename|>core/server/api/v2/mail.js<|end_filename|>
const Promise = require('bluebird');
const common = require('../../lib/common');
const mailService = require('../../services/mail');
const api = require('./');
let mailer;
let _private = {};

_private.sendMail = (object) => {
    if (!(mailer instanceof mailService.GhostMailer)) {
        mailer = new mailService.GhostMailer();
    }

    return mailer.send(object.mail[0].message).catch((err) => {
        if (mailer.state.usingDirect) {
            api.notifications.add(
                {
                    notifications: [{
                        type: 'warn',
                        message: [
                            common.i18n.t('warnings.index.unableToSendEmail'),
                            common.i18n.t('common.seeLinkForInstructions', {link: 'https://docs.ghost.org/mail/'})
                        ].join(' ')
                    }]
                },
                {context: {internal: true}}
            );
        }

        return Promise.reject(err);
    });
};

module.exports = {
    docName: 'mail',

    send: {
        permissions: true,
        query(frame) {
            return _private.sendMail(frame.data);
        }
    },

    sendTest(frame) {
        return mailService.utils.generateContent({template: 'test'})
            .then((content) => {
                const payload = {
                    mail: [{
                        message: {
                            to: frame.user.get('email'),
                            subject: common.i18n.t('common.api.mail.testGhostEmail'),
                            html: content.html,
                            text: content.text
                        }
                    }]
                };

                return _private.sendMail(payload);
            });
    }
};


<|start_filename|>core/server/services/auth/api-key/content.js<|end_filename|>
const models = require('../../../models');
const common = require('../../../lib/common');

const authenticateContentApiKey = function authenticateContentApiKey(req, res, next) {
    // allow fallthrough to other auth methods or final ensureAuthenticated check
    if (!req.query || !req.query.key) {
        return next();
    }

    let key = req.query.key;

    models.ApiKey.findOne({secret: key}).then((apiKey) => {
        if (!apiKey) {
            return next(new common.errors.UnauthorizedError({
                message: common.i18n.t('errors.middleware.auth.unknownContentApiKey'),
                code: 'UNKNOWN_CONTENT_API_KEY'
            }));
        }

        if (apiKey.get('type') !== 'content') {
            return next(new common.errors.UnauthorizedError({
                message: common.i18n.t('errors.middleware.auth.invalidApiKeyType'),
                code: 'INVALID_API_KEY_TYPE'
            }));
        }

        // authenticated OK, store the api key on the request for later checks and logging
        req.api_key = apiKey;
        next();
    }).catch((err) => {
        next(new common.errors.InternalServerError({err}));
    });
};

module.exports = {
    authenticateContentApiKey
};


<|start_filename|>core/server/lib/members/static/auth/components/FormFooter.js<|end_filename|>
export default ({title, hash, label}) => (
    <div className="gm-auth-footer">
        <div className="flex items-baseline">
            <h4>{ title }</h4>
            <a href={hash}>
                { label }
            </a>
        </div>
    </div>
);


<|start_filename|>core/server/api/v0.1/webhooks.js<|end_filename|>
// # Webhooks API
// RESTful API for creating webhooks
// also known as "REST Hooks", see http://resthooks.org
const Promise = require('bluebird'),
    _ = require('lodash'),
    pipeline = require('../../lib/promise/pipeline'),
    localUtils = require('./utils'),
    models = require('../../models'),
    common = require('../../lib/common'),
    docName = 'webhooks';

let webhooks;

/**
 * ## Webhook API Methods
 *
 * **See:** [API Methods](constants.js.html#api%20methods)
 */
webhooks = {

    /**
     * ### Add
     * @param {Webhook} object the webhook to create
     * @returns {Promise(Webhook)} newly created Webhook
     */
    add(object, options) {
        let tasks;

        /**
         * ### Model Query
         * Make the call to the Model layer
         * @param {Object} options
         * @returns {Object} options
         */
        function doQuery(options) {
            return models.Webhook.getByEventAndTarget(options.data.webhooks[0].event, options.data.webhooks[0].target_url, _.omit(options, ['data']))
                .then((webhook) => {
                    if (webhook) {
                        return Promise.reject(new common.errors.ValidationError({message: common.i18n.t('errors.api.webhooks.webhookAlreadyExists')}));
                    }

                    return models.Webhook.add(options.data.webhooks[0], _.omit(options, ['data']));
                })
                .then((model) => {
                    return {
                        webhooks: [model.toJSON(options)]
                    };
                });
        }

        // Push all of our tasks into a `tasks` array in the correct order
        tasks = [
            localUtils.validate(docName),
            localUtils.convertOptions(),
            localUtils.handlePermissions(docName, 'add'),
            doQuery
        ];

        // Pipeline calls each task passing the result of one to be the arguments for the next
        return pipeline(tasks, object, options);
    },

    /**
     * ## Destroy
     *
     * @public
     * @param {{id, context}} options
     * @return {Promise}
     */
    destroy(options) {
        let tasks;

        /**
         * ### Delete Webhook
         * Make the call to the Model layer
         * @param {Object} options
         */
        function doQuery(options) {
            return models.Webhook.destroy(options).return(null);
        }

        // Push all of our tasks into a `tasks` array in the correct order
        tasks = [
            localUtils.validate(docName, {opts: localUtils.idDefaultOptions}),
            localUtils.convertOptions(),
            localUtils.handlePermissions(docName, 'destroy'),
            doQuery
        ];

        // Pipeline calls each task passing the result of one to be the arguments for the next
        return pipeline(tasks, options);
    }
};

module.exports = webhooks;


<|start_filename|>core/server/web/shared/middlewares/cache-control.js<|end_filename|>
// # CacheControl Middleware
// Usage: cacheControl(profile), where profile is one of 'public' or 'private'
// After: checkIsPrivate
// Before: routes
// App: Admin|Site|API
//
// Allows each app to declare its own default caching rules

const isString = require('lodash/isString');
const config = require('../../../config');

const cacheControl = (options) => {
    const profiles = {
        public: 'public, max-age=' + config.get('caching:frontend:maxAge'),
        private: 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
    };

    let output;

    if (isString(options) && profiles.hasOwnProperty(options)) {
        output = profiles[options];
    }

    return function cacheControlHeaders(req, res, next) {
        if (output) {
            if (res.isPrivateBlog) {
                res.set({'Cache-Control': profiles.private});
            } else {
                res.set({'Cache-Control': output});
            }
        }
        next();
    };
};

module.exports = cacheControl;


<|start_filename|>core/server/web/shared/middlewares/ghost-locals.js<|end_filename|>
const ghostVersion = require('../../../lib/ghost-version');
const themeService = require('../../../services/themes');

// ### GhostLocals Middleware
// Expose the standard locals that every request will need to have available
module.exports = function ghostLocals(req, res, next) {
    // Make sure we have a locals value.
    res.locals = res.locals || {};
    // The current Ghost version
    res.locals.version = ghostVersion.full;
    // The current Ghost version, but only major.minor
    res.locals.safeVersion = ghostVersion.safe;
    // relative path from the URL
    res.locals.relativeUrl = req.path;
    // make ghost api version available for the theme + routing
    res.locals.apiVersion = themeService.getApiVersion();

    next();
};


<|start_filename|>core/server/lib/members/static/auth/postcss.config.js<|end_filename|>
module.exports = {
    plugins: [
        require('postcss-import'),
        require('autoprefixer'),
        require('postcss-css-variables'),
        require('postcss-color-mod-function'),
        require('cssnano'),
        require('postcss-custom-properties')
    ]
};


<|start_filename|>core/server/lib/mobiledoc/index.js<|end_filename|>
module.exports = {
    activate() {
        // needed by ghost
    },

    get cards() {
        return require('./cards');
    },

    get atoms() {
        return require('./atoms');
    },

    get converters() {
        return require('./converters');
    }
};


<|start_filename|>core/server/api/v2/redirects.js<|end_filename|>
const fs = require('fs-extra');
const path = require('path');
const Promise = require('bluebird');
const moment = require('moment-timezone');
const config = require('../../config');
const common = require('../../lib/common');
const validation = require('../../data/validation');
const web = require('../../web');

const _private = {};

_private.readRedirectsFile = (customRedirectsPath) => {
    const redirectsPath = customRedirectsPath || path.join(config.getContentPath('data'), 'redirects.json');

    return fs.readFile(redirectsPath, 'utf-8')
        .then((content) => {
            try {
                content = JSON.parse(content);
            } catch (err) {
                throw new common.errors.BadRequestError({
                    message: common.i18n.t('errors.general.jsonParse', {context: err.message})
                });
            }

            return content;
        })
        .catch((err) => {
            if (err.code === 'ENOENT') {
                return Promise.resolve([]);
            }

            if (common.errors.utils.isIgnitionError(err)) {
                throw err;
            }

            throw new common.errors.NotFoundError({
                err: err
            });
        });
};

module.exports = {
    docName: 'redirects',

    download: {
        headers: {
            disposition: {
                type: 'file',
                value: 'redirects.json'
            }
        },
        permissions: true,
        query() {
            return _private.readRedirectsFile();
        }
    },

    upload: {
        permissions: true,
        headers: {
            cacheInvalidate: true
        },
        query(frame) {
            const redirectsPath = path.join(config.getContentPath('data'), 'redirects.json');
            const backupRedirectsPath = path.join(config.getContentPath('data'), `redirects-${moment().format('YYYY-MM-DD-HH-mm-ss')}.json`);

            return fs.pathExists(redirectsPath)
                .then((exists) => {
                    if (!exists) {
                        return null;
                    }

                    return fs.pathExists(backupRedirectsPath)
                        .then((exists) => {
                            if (!exists) {
                                return null;
                            }

                            return fs.unlink(backupRedirectsPath);
                        })
                        .then(() => {
                            return fs.move(redirectsPath, backupRedirectsPath);
                        });
                })
                .then(() => {
                    return _private.readRedirectsFile(frame.file.path)
                        .then((content) => {
                            validation.validateRedirects(content);
                            return fs.writeFile(redirectsPath, JSON.stringify(content), 'utf-8');
                        })
                        .then(() => {
                            // CASE: trigger that redirects are getting re-registered
                            web.shared.middlewares.customRedirects.reload();
                        });
                });
        }
    }
};


<|start_filename|>core/server/web/shared/index.js<|end_filename|>
module.exports = {
    get middlewares() {
        return require('./middlewares');
    },

    get utils() {
        return require('./utils');
    }
};


<|start_filename|>core/server/lib/common/logging.js<|end_filename|>
const config = require('../../config'),
    {logging} = require('ghost-ignition');

module.exports = logging({
    env: config.get('env'),
    path: config.get('logging:path') || config.getContentPath('logs'),
    domain: config.get('url'),
    mode: config.get('logging:mode'),
    level: config.get('logging:level'),
    transports: config.get('logging:transports'),
    loggly: config.get('logging:loggly'),
    rotation: config.get('logging:rotation')
});


<|start_filename|>core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js<|end_filename|>
const logging = require('../../../../lib/common/logging');
const merge = require('lodash/merge');
const models = require('../../../../models');
const utils = require('../../../schema/fixtures/utils');

const _private = {};

_private.printResult = function printResult(result, message) {
    if (result.done === result.expected) {
        logging.info(message);
    } else {
        logging.warn(`(${result.done}/${result.expected}) ${message}`);
    }
};

_private.addApiKeyRole = (options) => {
    const message = 'Adding "Admin Integration" role to roles table';
    const apiKeyRole = utils.findModelFixtureEntry('Role', {name: 'Admin Integration'});

    return models.Role.findOne({name: apiKeyRole.name}, options)
        .then((role) => {
            if (!role) {
                return utils.addFixturesForModel({
                    name: 'Role',
                    entries: [apiKeyRole]
                }, options).then(result => _private.printResult(result, message));
            }

            logging.warn(message);
        });
};

_private.addApiKeyPermissions = (options) => {
    const message = 'Adding permissions for the "Admin Integration" role';
    const relations = utils.findRelationFixture('Role', 'Permission');

    return utils.addFixturesForRelation({
        from: relations.from,
        to: relations.to,
        entries: {
            'Admin Integration': relations.entries['Admin Integration']
        }
    }, options).then(result => _private.printResult(result, message));
};

_private.removeApiKeyPermissionsAndRole = (options) => {
    const message = 'Rollback: Removing "Admin Integration" role and permissions';

    return models.Role.findOne({name: 'Admin Integration'}, options)
        .then((role) => {
            if (!role) {
                logging.warn(message);
                return;
            }

            return role.destroy().then(() => {
                logging.info(message);
            });
        });
};

module.exports.config = {
    transaction: true
};

module.exports.up = (options) => {
    const localOptions = merge({
        context: {internal: true},
        migrating: true
    }, options);

    return _private.addApiKeyRole(localOptions)
        .then(() => _private.addApiKeyPermissions(localOptions));
};

module.exports.down = (options) => {
    const localOptions = merge({
        context: {internal: true},
        migrating: true
    }, options);

    return _private.removeApiKeyPermissionsAndRole(localOptions);
};


<|start_filename|>core/server/lib/mobiledoc/cards/index.js<|end_filename|>
module.exports = [
    require('./card-markdown'),
    require('./code'),
    require('./embed'),
    require('./hr'),
    require('./html'),
    require('./image'),
    require('./markdown'),
    require('./gallery')
];


<|start_filename|>core/server/web/site/routes.js<|end_filename|>
const routing = require('../../services/routing');

module.exports = function siteRoutes(options = {}) {
    return routing.bootstrap.init(options);
};


<|start_filename|>core/server/lib/mobiledoc/cards/card-markdown.js<|end_filename|>
// this card is just an alias of the `markdown` card which is necessary because
// our markdown-only editor was using the `card-markdown` card name
const markdownCard = require('./markdown');
const createCard = require('../create-card');

module.exports = createCard(
    Object.assign({}, markdownCard, {name: 'card-markdown'})
);


<|start_filename|>core/server/api/v2/utils/serializers/input/utils/url.js<|end_filename|>
const _ = require('lodash');
const {absoluteToRelative, getBlogUrl, STATIC_IMAGE_URL_PREFIX} = require('../../../../../../services/url/utils');

const handleCanonicalUrl = (url) => {
    const blogDomain = getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
    const absolute = url.replace(/^http(s?):\/\//, '');

    if (absolute.startsWith(blogDomain)) {
        return absoluteToRelative(url, {withoutSubdirectory: true});
    }

    return url;
};

const handleImageUrl = (imageUrl) => {
    const blogDomain = getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
    const imageUrlAbsolute = imageUrl.replace(/^http(s?):\/\//, '');
    const imagePathRe = new RegExp(`^${blogDomain}/${STATIC_IMAGE_URL_PREFIX}`);

    if (imagePathRe.test(imageUrlAbsolute)) {
        return absoluteToRelative(imageUrl);
    }

    return imageUrl;
};

const handleContentUrls = (content) => {
    const blogDomain = getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
    const imagePathRe = new RegExp(`(http(s?)://)?${blogDomain}/${STATIC_IMAGE_URL_PREFIX}`, 'g');

    const matches = _.uniq(content.match(imagePathRe));

    if (matches) {
        matches.forEach((match) => {
            const relative = absoluteToRelative(match);
            content = content.replace(new RegExp(match, 'g'), relative);
        });
    }

    return content;
};

const forPost = (attrs, options) => {
    // make all content image URLs relative, ref: https://github.com/TryGhost/Ghost/issues/10477
    if (attrs.mobiledoc) {
        attrs.mobiledoc = handleContentUrls(attrs.mobiledoc);
    }

    if (attrs.feature_image) {
        attrs.feature_image = handleImageUrl(attrs.feature_image);
    }

    if (attrs.og_image) {
        attrs.og_image = handleImageUrl(attrs.og_image);
    }

    if (attrs.twitter_image) {
        attrs.twitter_image = handleImageUrl(attrs.twitter_image);
    }

    if (attrs.canonical_url) {
        attrs.canonical_url = handleCanonicalUrl(attrs.canonical_url);
    }

    if (options && options.withRelated) {
        options.withRelated.forEach((relation) => {
            if (relation === 'tags' && attrs.tags) {
                attrs.tags = attrs.tags.map(tag => forTag(tag));
            }

            if (relation === 'author' && attrs.author) {
                attrs.author = forUser(attrs.author, options);
            }

            if (relation === 'authors' && attrs.authors) {
                attrs.authors = attrs.authors.map(author => forUser(author, options));
            }
        });
    }

    return attrs;
};

const forUser = (attrs) => {
    if (attrs.profile_image) {
        attrs.profile_image = handleImageUrl(attrs.profile_image);
    }

    if (attrs.cover_image) {
        attrs.cover_image = handleImageUrl(attrs.cover_image);
    }

    return attrs;
};

const forTag = (attrs) => {
    if (attrs.feature_image) {
        attrs.feature_image = handleImageUrl(attrs.feature_image);
    }

    return attrs;
};

const forSetting = (attrs) => {
    if (attrs.value) {
        attrs.value = handleImageUrl(attrs.value);
    }

    return attrs;
};

module.exports.forPost = forPost;
module.exports.forUser = forUser;
module.exports.forTag = forTag;
module.exports.forSetting = forSetting;


<|start_filename|>core/server/models/member.js<|end_filename|>
const ghostBookshelf = require('./base');
const security = require('../lib/security');

const Member = ghostBookshelf.Model.extend({
    tableName: 'members',

    onSaving() {
        ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);

        if (this.hasChanged('password')) {
            return security.password.hash(String(this.get('password')))
                .then((hash) => {
                    this.set('password', hash);
                });
        }
    },

    comparePassword(rawPassword) {
        return security.password.compare(rawPassword, this.get('password'));
    },

    toJSON(unfilteredOptions) {
        var options = Member.filterOptions(unfilteredOptions, 'toJSON'),
            attrs = ghostBookshelf.Model.prototype.toJSON.call(this, options);

        // remove password hash and tokens for security reasons
        delete attrs.password;

        return attrs;
    }
});

const Members = ghostBookshelf.Collection.extend({
    model: Member
});

module.exports = {
    Member: ghostBookshelf.model('Member', Member),
    Members: ghostBookshelf.collection('Members', Members)
};


<|start_filename|>core/server/lib/mobiledoc/converters/index.js<|end_filename|>
const common = require('../../common');

module.exports = {
    get mobiledocConverter() {
        return require('./mobiledoc-converter');
    },

    get markdownConverter() {
        return require('./markdown-converter');
    },

    get htmlToMobiledocConverter() {
        try {
            return require('@tryghost/html-to-mobiledoc').toMobiledoc;
        } catch (err) {
            if (process.versions.node.startsWith('v6.')) {
                // NOTE: When Node v6 is dropped this code block should be removed
                return () => {
                    throw new common.errors.InternalServerError({
                        message: 'Unable to convert from source HTML to Mobiledoc',
                        context: 'The html-to-mobiledoc package was not installed',
                        help: 'Please upgrade to Node.js v10',
                        code: 'HTML_TO_MOBILEDOC_INSTALLATION',
                        err: err
                    });
                };
            } else {
                return () => {
                    throw new common.errors.InternalServerError({
                        message: 'Unable to convert from source HTML to Mobiledoc',
                        context: 'The html-to-mobiledoc package was not installed',
                        help: 'Please review any errors from the install process by checking the Ghost logs',
                        code: 'HTML_TO_MOBILEDOC_INSTALLATION',
                        err: err
                    });
                };
            }
        }
    }
};


<|start_filename|>core/server/lib/members/static/auth/components/Pages.js<|end_filename|>
import { Component } from 'preact';
import { IconClose, GhostLogo } from './icons';

export default class Pages extends Component {
    constructor(props) {
        super(props);
        this.state = this.getStateFromBrowser();
        window.addEventListener("hashchange", () => this.onHashChange(), false);
        this.handleChange = props.onChange || (() => { });
    }

    getStateFromBrowser() {
        const [fullMatch, hash, query] = window.location.hash.match(/^#([^?]+)\??(.*)$/) || ['#', '', ''];
        return {
            hash,
            query,
            fullMatch
        };
    }

    onHashChange() {
        this.setState(this.getStateFromBrowser());
        this.handleChange();
    }

    filterChildren(children, state) {
        return children.filter((child) => {
            return child.attributes.hash === state.hash;
        }).map((child) => {
            child.attributes.frameLocation = { ...this.state };
            return child;
        });
    }

    render({ children, className, onClick, stripeConfig, siteConfig }, state) {
        let modalClassName = "gm-modal gm-auth-modal";
        if (state.hash === 'signup' && stripeConfig) {
            modalClassName += " gm-subscribe-modal"
        }
        let iconUrl = siteConfig && siteConfig.icon;
        let title = (siteConfig && siteConfig.title) || "Ghost Publication";
        let iconStyle = iconUrl ? {
            backgroundImage: `url(${iconUrl})`,
            backgroundSize: `38px`
        } : {};
        return (
            <div className={className}>
                <div className="gm-modal-header">
                    <div className="gm-logo" style={iconStyle}></div>
                    <h2>{title}</h2>
                </div>
                <div className="gm-modal-close" onClick={ onClick }>{IconClose}</div>
                <div className="gm-modal-container">
                    <div className={modalClassName} onClick={(e) => e.stopPropagation()}>
                        {this.filterChildren(children, state)}
                    </div>
                </div>
                <div className="gm-powered-by">
                    <a href="https://ghost.org" target="_blank"><span>Powered by</span> {GhostLogo}</a>
                </div>
            </div>
        );
    }
}


<|start_filename|>core/server/api/v2/members.js<|end_filename|>
const memberUserObject = require('../../services/members').api.memberUserObject;

const members = {
    docName: 'members',
    browse: {
        options: [
            'limit',
            'fields',
            'filter',
            'order',
            'debug',
            'page'
        ],
        permissions: true,
        validation: {},
        query(frame) {
            return memberUserObject.list(frame.options);
        }
    },

    read: {
        headers: {},
        data: [
            'id',
            'email'
        ],
        validation: {},
        permissions: true,
        query(frame) {
            return memberUserObject.get(frame.data, frame.options);
        }
    }
};

module.exports = members;


<|start_filename|>index.js<|end_filename|>
// # Ghost Startup
// Orchestrates the startup of Ghost when run from command line.

var startTime = Date.now(),
    debug = require('ghost-ignition').debug('boot:index'),
    ghost, express, common, urlService, parentApp;

debug('First requires...');

ghost = require('./core');

debug('Required ghost');

express = require('express');
common = require('./core/server/lib/common');
urlService = require('./core/server/services/url');
parentApp = express();

debug('Initialising Ghost');
ghost().then(function (ghostServer) {
    // Mount our Ghost instance on our desired subdirectory path if it exists.
    parentApp.use(urlService.utils.getSubdir(), ghostServer.rootApp);

    debug('Starting Ghost');
    // Let Ghost handle starting our server instance.
    return ghostServer.start(parentApp)
        .then(function afterStart() {
            common.logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
        });
}).catch(function (err) {
    common.logging.error(err);
    setTimeout(() => {
        process.exit(-1);
    }, 100);
});


<|start_filename|>core/server/api/v2/utils/serializers/input/integrations.js<|end_filename|>
const _ = require('lodash');
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:input:integrations');

module.exports = {
    add(apiConfig, frame) {
        debug('add');

        frame.data = _.pick(frame.data.integrations[0], apiConfig.data);
    },
    edit(apiConfig, frame) {
        debug('edit');

        frame.data = _.pick(frame.data.integrations[0], apiConfig.data);
    }
};


<|start_filename|>core/server/services/routing/index.js<|end_filename|>
module.exports = {
    get bootstrap() {
        return require('./bootstrap');
    },

    get registry() {
        return require('./registry');
    },

    get helpers() {
        return require('./helpers');
    },

    get CollectionRouter() {
        return require('./CollectionRouter');
    },

    get TaxonomyRouter() {
        return require('./TaxonomyRouter');
    }
};


<|start_filename|>core/server/api/v2/settings-public.js<|end_filename|>
const settingsCache = require('../../services/settings/cache');

module.exports = {
    docName: 'settings',

    browse: {
        permissions: true,
        query() {
            // @TODO: decouple settings cache from API knowledge
            // The controller fetches models (or cached models) and the API frame for the target API version formats the response.
            return settingsCache.getPublic();
        }
    }
};


<|start_filename|>core/server/lib/mobiledoc/create-card.js<|end_filename|>
module.exports = function createCard(card) {
    const {name, type} = card;

    return {
        name,
        type,
        render({env, payload, options}) {
            const {dom} = env;
            const cleanName = name.replace(/^card-/, '');

            const cardOutput = card.render({env, payload, options});

            if (!cardOutput) {
                return cardOutput;
            }

            const beginComment = dom.createComment(`kg-card-begin: ${cleanName}`);
            const endComment = dom.createComment(`kg-card-end: ${cleanName}`);
            const fragment = dom.createDocumentFragment();

            fragment.appendChild(beginComment);
            fragment.appendChild(cardOutput);
            fragment.appendChild(endComment);

            return fragment;
        }
    };
};


<|start_filename|>core/server/web/shared/middlewares/validation/profile-image.js<|end_filename|>
const common = require('../../../../lib/common');
const imageLib = require('../../../../lib/image');

module.exports = function profileImage(req, res, next) {
    // we checked for a valid image file, now we need to do validations for profile image
    imageLib.imageSize.getImageSizeFromPath(req.file.path).then((response) => {
        // save the image dimensions in new property for file
        req.file.dimensions = response;

        // CASE: file needs to be a square
        if (req.file.dimensions.width !== req.file.dimensions.height) {
            return next(new common.errors.ValidationError({
                message: common.i18n.t('errors.api.images.isNotSquare')
            }));
        }

        next();
    }).catch((err) => {
        next(err);
    });
};


<|start_filename|>core/server/lib/members/static/auth/components/FormInput.js<|end_filename|>
export default ({type, name, placeholder, value = '', error, onInput, required, className, children, icon}) => (
    <div className="gm-form-element">
        <div className={[
                (className ? className : ""),
                "gm-input"
                ].join(' ')}>
            <input
                type={ type }
                name={ name }
                key={ name }
                placeholder={ placeholder }
                value={ value }
                onInput={ (e) => onInput(e, name) }
                required={ required }
                className={[
                    (value ? "gm-input-filled" : ""),
                    (error ? "gm-error" : "")
                ].join(' ')}
            />
            <i>{ icon }</i>
            { children }
        </div>
    </div>
);


<|start_filename|>core/server/api/index.js<|end_filename|>
module.exports = require('./v0.1');
module.exports['v0.1'] = require('./v0.1');
module.exports.v2 = require('./v2');
module.exports.shared = require('./shared');


<|start_filename|>core/server/lib/members/static/auth/components/FormHeaderCTA.js<|end_filename|>
export default ({title, label, icon, hash}) => (
    <div className="gm-auth-cta">
        {title ? (<h4>{ title }</h4>) : ""}
        <a href={hash}>
            { label }
            { icon }
        </a>
    </div>
);


<|start_filename|>core/server/lib/members/users.js<|end_filename|>
module.exports = function ({
    subscriptions,
    createMember,
    updateMember,
    getMember,
    listMembers,
    validateMember,
    sendEmail,
    encodeToken,
    decodeToken
}) {
    function requestPasswordReset({email}) {
        return getMember({email}, {require: true}).then((member) => {
            return encodeToken({
                sub: member.id
            }).then((token) => {
                return sendEmail(member, {token});
            });
        }, (/*err*/) => {
            // Ignore user not found err;
        });
    }

    function resetPassword({token, password}) {
        return decodeToken(token).then(({sub}) => {
            return updateMember({id: sub}, {password});
        });
    }

    function get(...args) {
        return getMember(...args).then((member) => {
            return subscriptions.getAdapters().then((adapters) => {
                return Promise.all(adapters.map((adapter) => {
                    return subscriptions.getSubscription(member, {
                        adapter
                    }).then((subscription) => {
                        return Object.assign(subscription, {adapter});
                    });
                }));
            }).then((subscriptions) => {
                return Object.assign({}, member, {
                    subscriptions: subscriptions.filter(sub => sub.status === 'active')
                });
            });
        });
    }

    return {
        requestPasswordReset,
        resetPassword,
        create: createMember,
        validate: validateMember,
        list: listMembers,
        get
    };
};


<|start_filename|>core/server/lib/members/static/auth/components/CheckoutForm.js<|end_filename|>
import React, { Component } from 'react';
import { CardElement } from 'react-stripe-elements';

class CheckoutForm extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        let style = {
            base: {
                '::placeholder': {
                    color: '#8795A1',
                    fontSize: '15px'
                }
            },
            invalid: {
                '::placeholder': {
                    color: 'rgba(240, 82, 48, 0.75)'
                }
            }
        };
        return (
            <div className="gm-form-element">
                <CardElement style={ style } />
            </div>
        );
    }
}

export default CheckoutForm;


<|start_filename|>core/server/services/routing/controllers/channel.js<|end_filename|>
const _ = require('lodash'),
    debug = require('ghost-ignition').debug('services:routing:controllers:channel'),
    common = require('../../../lib/common'),
    security = require('../../../lib/security'),
    themes = require('../../themes'),
    filters = require('../../../filters'),
    helpers = require('../helpers');

// @TODO: the collection+rss controller does almost the same
module.exports = function channelController(req, res, next) {
    debug('channelController', req.params, res.routerOptions);

    const pathOptions = {
        page: req.params.page !== undefined ? req.params.page : 1,
        slug: req.params.slug ? security.string.safe(req.params.slug) : undefined
    };

    if (pathOptions.page) {
        // CASE 1: routes.yaml `limit` is stronger than theme definition
        // CASE 2: use `posts_per_page` config from theme as `limit` value
        if (res.routerOptions.limit) {
            themes.getActive().updateTemplateOptions({
                data: {
                    config: {
                        posts_per_page: res.routerOptions.limit
                    }
                }
            });

            pathOptions.limit = res.routerOptions.limit;
        } else {
            const postsPerPage = parseInt(themes.getActive().config('posts_per_page'));

            if (!isNaN(postsPerPage) && postsPerPage > 0) {
                pathOptions.limit = postsPerPage;
            }
        }
    }

    return helpers.fetchData(pathOptions, res.routerOptions, res.locals)
        .then(function handleResult(result) {
            // CASE: requested page is greater than number of pages we have
            if (pathOptions.page > result.meta.pagination.pages) {
                return next(new common.errors.NotFoundError({
                    message: common.i18n.t('errors.errors.pageNotFound')
                }));
            }

            // Format data 1
            // @TODO: figure out if this can be removed, it's supposed to ensure that absolutely URLs get generated
            // correctly for the various objects, but I believe it doesn't work and a different approach is needed.
            helpers.secure(req, result.posts);

            // @TODO: get rid of this O_O
            _.each(result.data, function (data) {
                helpers.secure(req, data);
            });

            // @TODO: properly design these filters
            filters.doFilter('prePostsRender', result.posts, res.locals)
                .then(function (posts) {
                    result.posts = posts;
                    return result;
                })
                .then(helpers.renderEntries(req, res));
        })
        .catch(helpers.handleError(next));
};


<|start_filename|>core/server/lib/members/static/auth/styles/members.css<|end_filename|>
@import './normalize.css';
@import './utils.css';
@import './variables.css';
@import './components.css';
@import './screen.css';

<|start_filename|>core/server/helpers/pagination.js<|end_filename|>
// ### Pagination Helper
// `{{pagination}}`
// Outputs previous and next buttons, along with info about the current page

var proxy = require('./proxy'),
    _ = require('lodash'),
    errors = proxy.errors,
    i18n = proxy.i18n,
    createFrame = proxy.hbs.handlebars.createFrame,
    templates = proxy.templates,
    pagination;

pagination = function (options) {
    options = options || {};
    options.hash = options.hash || {};
    options.data = options.data || {};

    if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
        throw new errors.IncorrectUsageError({
            level: 'normal',
            message: i18n.t('warnings.helpers.pagination.invalidData'),
            help: 'https://docs.ghost.org/api/handlebars-themes/helpers/pagination/'
        });
    }

    if (_.isUndefined(this.pagination.page) || _.isUndefined(this.pagination.pages) ||
        _.isUndefined(this.pagination.total) || _.isUndefined(this.pagination.limit)) {
        throw new errors.IncorrectUsageError({
            message: i18n.t('warnings.helpers.pagination.valuesMustBeDefined')
        });
    }

    if ((!_.isNull(this.pagination.next) && !_.isNumber(this.pagination.next)) ||
        (!_.isNull(this.pagination.prev) && !_.isNumber(this.pagination.prev))) {
        throw new errors.IncorrectUsageError({
            message: i18n.t('warnings.helpers.pagination.nextPrevValuesMustBeNumeric')
        });
    }

    if (!_.isNumber(this.pagination.page) || !_.isNumber(this.pagination.pages) ||
        !_.isNumber(this.pagination.total) || !_.isNumber(this.pagination.limit)) {
        throw new errors.IncorrectUsageError({message: i18n.t('warnings.helpers.pagination.valuesMustBeNumeric')});
    }
    const context = _.merge({}, this, options.hash, this.pagination);
    const data = createFrame(options.data);

    return templates.execute('pagination', context, {data});
};

module.exports = pagination;


<|start_filename|>core/server/services/routing/CollectionRouter.js<|end_filename|>
const debug = require('ghost-ignition').debug('services:routing:collection-router');
const common = require('../../lib/common');
const urlService = require('../url');
const ParentRouter = require('./ParentRouter');

const controllers = require('./controllers');
const middlewares = require('./middlewares');
const RSSRouter = require('./RSSRouter');

class CollectionRouter extends ParentRouter {
    constructor(mainRoute, object, RESOURCE_CONFIG) {
        super('CollectionRouter');

        this.RESOURCE_CONFIG = RESOURCE_CONFIG.QUERY.post;

        this.routerName = mainRoute === '/' ? 'index' : mainRoute.replace(/\//g, '');

        // NOTE: index/parent route e.g. /, /podcast/, /magic/ ;)
        this.route = {
            value: mainRoute
        };

        this.rss = object.rss !== false;

        this.permalinks = {
            originalValue: object.permalink,
            value: object.permalink
        };

        // @NOTE: see helpers/templates - we use unshift to prepend the templates
        this.templates = (object.templates || []).reverse();

        this.filter = object.filter;
        this.data = object.data || {query: {}, router: {}};
        this.order = object.order;
        this.limit = object.limit;

        this.permalinks.getValue = (options) => {
            options = options || {};

            // @NOTE: url options are only required when registering urls in express.
            //        e.g. the UrlService will access the routes and doesn't want to know about possible url options
            if (options.withUrlOptions) {
                return urlService.utils.urlJoin(this.permalinks.value, '/:options(edit)?/');
            }

            return this.permalinks.value;
        };

        this.context = [this.routerName];

        debug(this.name, this.route, this.permalinks);

        this._registerRoutes();
        this._listeners();
    }

    _registerRoutes() {
        // REGISTER: context middleware for this collection
        this.router().use(this._prepareEntriesContext.bind(this));

        // REGISTER: collection route e.g. /, /podcast/
        this.mountRoute(this.route.value, controllers.collection);

        // REGISTER: enable pagination by default
        this.router().param('page', middlewares.pageParam);
        this.mountRoute(urlService.utils.urlJoin(this.route.value, 'page', ':page(\\d+)'), controllers.collection);

        // REGISTER: is rss enabled?
        if (this.rss) {
            this.rssRouter = new RSSRouter();
            this.mountRouter(this.route.value, this.rssRouter.router());
        }

        // REGISTER: context middleware for entries
        this.router().use(this._prepareEntryContext.bind(this));

        // REGISTER: page/post resource redirects
        this.router().param('slug', this._respectDominantRouter.bind(this));

        // REGISTER: permalinks e.g. /:slug/, /podcast/:slug
        this.mountRoute(this.permalinks.getValue({withUrlOptions: true}), controllers.entry);

        common.events.emit('router.created', this);
    }

    /**
     * We attach context information of the router to the request.
     * By this we can e.g. access the router options in controllers.
     */
    _prepareEntriesContext(req, res, next) {
        res.routerOptions = {
            type: 'collection',
            filter: this.filter,
            limit: this.limit,
            order: this.order,
            permalinks: this.permalinks.getValue({withUrlOptions: true}),
            resourceType: this.getResourceType(),
            query: this.RESOURCE_CONFIG,
            context: this.context,
            frontPageTemplate: 'home',
            templates: this.templates,
            identifier: this.identifier,
            name: this.routerName,
            data: this.data.query
        };

        next();
    }

    _prepareEntryContext(req, res, next) {
        res.routerOptions.context = ['post'];
        res.routerOptions.type = 'entry';
        next();
    }

    _listeners() {
        /**
         * CASE: timezone changes
         *
         * If your permalink contains a date reference, we have to regenerate the urls.
         *
         * e.g. /:year/:month/:day/:slug/ or /:day/:slug/
         */
        this._onTimezoneEditedListener = this._onTimezoneEdited.bind(this);
        common.events.on('settings.active_timezone.edited', this._onTimezoneEditedListener);
    }

    _onTimezoneEdited(settingModel) {
        const newTimezone = settingModel.attributes.value,
            previousTimezone = settingModel._previousAttributes.value;

        if (newTimezone === previousTimezone) {
            return;
        }

        if (this.getPermalinks().getValue().match(/:year|:month|:day/)) {
            debug('_onTimezoneEdited: trigger regeneration');
            this.emit('updated');
        }
    }

    getResourceType() {
        return this.RESOURCE_CONFIG.resourceAlias || this.RESOURCE_CONFIG.resource;
    }

    getRoute(options) {
        options = options || {};

        return urlService.utils.createUrl(this.route.value, options.absolute, options.secure);
    }

    getRssUrl(options) {
        if (!this.rss) {
            return null;
        }

        return urlService.utils.createUrl(urlService.utils.urlJoin(this.route.value, this.rssRouter.route.value), options.absolute, options.secure);
    }

    reset() {
        if (this._onTimezoneEditedListener) {
            common.events.removeListener('settings.active_timezone.edited', this._onTimezoneEditedListener);
        }
    }
}

module.exports = CollectionRouter;


<|start_filename|>core/server/lib/members/util.js<|end_filename|>
function getData(...props) {
    return function (req, res, next) {
        if (!req.body) {
            res.writeHead(400);
            return res.end();
        }

        const data = props.concat('origin').reduce((data, prop) => {
            if (!data || !req.body[prop]) {
                return null;
            }
            return Object.assign(data, {
                [prop]: req.body[prop]
            });
        }, {});

        if (!data) {
            res.writeHead(400);
            return res.end(`Expected {${props.join(', ')}}`);
        }
        req.data = data || {};
        next();
    };
}

function handleError(status, res) {
    return function () {
        res.writeHead(status);
        res.end();
    };
}

module.exports = {
    getData,
    handleError
};


<|start_filename|>core/server/lib/members/static/auth/components/EmailInput.js<|end_filename|>
import FormInput from './FormInput';
import { IconEmail } from './icons';

export default ({value, error, children, onInput, className}) => (
    <FormInput
        type="email"
        name="email"
        label="Email"
        value={value}
        error={error}
        icon={IconEmail}
        placeholder="Email..."
        required={true}
        className={className}
        onInput={onInput}>
        {children}
    </FormInput>
);


<|start_filename|>core/server/apps/subscribers/lib/helpers/input_email.js<|end_filename|>
// # Input Email Helper
// Usage: `{{input_email}}`
//
// Used by `{{subscribe_form}}`

// (less) dirty requires
const proxy = require('../../../../helpers/proxy');
const SafeString = proxy.SafeString;
const templates = proxy.templates;

// We use the name input_email to match the helper for consistency:
module.exports = function input_email(options) { // eslint-disable-line camelcase
    options = options || {};
    options.hash = options.hash || {};

    const className = (options.hash.class) ? options.hash.class : 'subscribe-email';
    let extras = '';

    if (options.hash.autofocus) {
        extras += 'autofocus="autofocus"';
    }

    if (options.hash.placeholder) {
        extras += ` placeholder="${options.hash.placeholder}"`;
    }

    if (options.hash.value) {
        extras += ` value="${options.hash.value}"`;
    }

    if (options.hash.id) {
        extras += ' id="' + options.hash.id + '"';
    }

    const output = templates.input({
        type: 'email',
        name: 'email',
        className,
        extras: (extras ? extras.trim() : '')
    });

    return new SafeString(output);
};



<|start_filename|>core/server/web/admin/controller.js<|end_filename|>
const debug = require('ghost-ignition').debug('web:admin:controller');
const path = require('path');
const config = require('../../config');
const updateCheck = require('../../update-check');
const common = require('../../lib/common');

// Route: index
// Path: /ghost/
// Method: GET
module.exports = function adminController(req, res) {
    debug('index called');

    // run in background, don't block the admin rendering
    updateCheck()
        .catch((err) => {
            common.logging.error(err);
        });

    const defaultTemplate = config.get('env') === 'production' ? 'default-prod.html' : 'default.html';
    const templatePath = path.resolve(config.get('paths').adminViews, defaultTemplate);

    res.sendFile(templatePath);
};


<|start_filename|>core/server/data/db/connection.js<|end_filename|>
var knex = require('knex'),
    config = require('../../config'),
    common = require('../../lib/common'),
    knexInstance;

// @TODO:
// - if you require this file before config file was loaded,
// - then this file is cached and you have no chance to connect to the db anymore
// - bring dynamic into this file (db.connect())
function configure(dbConfig) {
    var client = dbConfig.client;

    if (client === 'sqlite3') {
        dbConfig.useNullAsDefault = dbConfig.hasOwnProperty('useNullAsDefault') ? dbConfig.useNullAsDefault : true;
    }

    if (client === 'mysql') {
        dbConfig.connection.timezone = 'UTC';
        dbConfig.connection.charset = 'utf8mb4';

        dbConfig.connection.loggingHook = function loggingHook(err) {
            common.logging.error(new common.errors.InternalServerError({
                code: 'MYSQL_LOGGING_HOOK',
                err: err
            }));
        };
    }

    return dbConfig;
}

if (!knexInstance && config.get('database') && config.get('database').client) {
    knexInstance = knex(configure(config.get('database')));
}

module.exports = knexInstance;


<|start_filename|>core/server/lib/members/static/auth/Gruntfile.js<|end_filename|>
/* eslint-env node */
/* eslint-disable object-shorthand */
'use strict';

module.exports = function (grunt) {
    // Find all of the task which start with `grunt-` and load them, rather than explicitly declaring them all
    require('matchdep').filterDev(['grunt-*', '!grunt-cli']).forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        clean: {
            built: {
                src: ['dist/**']
            },
            dependencies: {
                src: ['node_modules/**']
            },
            tmp: {
                src: ['tmp/**']
            }
        },

        shell: {
            'npm-install': {
                command: 'yarn install'
            },

            preact: {
                command: function (mode) {
                    switch (mode) {
                    case 'prod':
                        return 'yarn build';
                    case 'dev':
                        return 'yarn dev';
                    }
                }
            },

            options: {
                preferLocal: true
            }
        }
    });

    grunt.registerTask('init', 'Install the preact member dependencies',
        ['shell:npm-install', 'shell:preact:prod']
    );
};


<|start_filename|>core/server/web/api/v2/content/middleware.js<|end_filename|>
const cors = require('cors');
const auth = require('../../../../services/auth');
const shared = require('../../../shared');

/**
 * Auth Middleware Packages
 *
 * IMPORTANT
 * - cors middleware MUST happen before pretty urls, because otherwise cors header can get lost on redirect
 * - url redirects MUST happen after cors, otherwise cors header can get lost on redirect
 */

/**
 * Authentication for public endpoints
 */
module.exports.authenticatePublic = [
    shared.middlewares.brute.contentApiKey,
    auth.authenticate.authenticateContentApi,
    auth.authorize.authorizeContentApi,
    cors(),
    shared.middlewares.urlRedirects.adminRedirect,
    shared.middlewares.prettyUrls
];


<|start_filename|>core/server/api/shared/frame.js<|end_filename|>
const debug = require('ghost-ignition').debug('api:shared:frame');
const _ = require('lodash');

class Frame {
    constructor(obj = {}) {
        this.original = obj;

        this.options = {};
        this.data = {};
        this.user = {};
        this.file = {};
        this.files = [];
        this.apiType = null;
    }

    /**
     * If you instantiate a new frame, all the data you pass in, land in `this.original`.
     * Based on the API ctrl implemented, this fn will pick allowed properties to either options or data.
     */
    configure(apiConfig) {
        debug('configure');

        if (apiConfig.options) {
            if (typeof apiConfig.options === 'function') {
                apiConfig.options = apiConfig.options(this);
            }

            if (this.original.hasOwnProperty('query')) {
                Object.assign(this.options, _.pick(this.original.query, apiConfig.options));
            }

            if (this.original.hasOwnProperty('params')) {
                Object.assign(this.options, _.pick(this.original.params, apiConfig.options));
            }

            if (this.original.hasOwnProperty('options')) {
                Object.assign(this.options, _.pick(this.original.options, apiConfig.options));
            }
        }

        this.options.context = this.original.context;

        if (this.original.body && Object.keys(this.original.body).length) {
            this.data = _.cloneDeep(this.original.body);
        } else {
            if (apiConfig.data) {
                if (typeof apiConfig.data === 'function') {
                    apiConfig.data = apiConfig.data(this);
                }

                if (this.original.hasOwnProperty('query')) {
                    Object.assign(this.data, _.pick(this.original.query, apiConfig.data));
                }

                if (this.original.hasOwnProperty('params')) {
                    Object.assign(this.data, _.pick(this.original.params, apiConfig.data));
                }

                if (this.original.hasOwnProperty('options')) {
                    Object.assign(this.data, _.pick(this.original.options, apiConfig.data));
                }
            }
        }

        this.user = this.original.user;
        this.file = this.original.file;
        this.files = this.original.files;

        debug('original', this.original);
        debug('options', this.options);
        debug('data', this.data);
    }
}

module.exports = Frame;


<|start_filename|>core/server/lib/members/static/auth/components/NameInput.js<|end_filename|>
import FormInput from './FormInput';
import { IconName } from './icons';

export default ({value, error, children, onInput, className}) => (
    <FormInput
        type="text"
        name="name"
        label="Name"
        value={value}
        error={error}
        icon={IconName}
        placeholder="Name..."
        required={true}
        className={className}
        onInput={onInput}>
        {children}
    </FormInput>
);


<|start_filename|>core/server/models/accesstoken.js<|end_filename|>
const ghostBookshelf = require('./base'),
    Basetoken = require('./base/token');

let Accesstoken,
    Accesstokens;

Accesstoken = Basetoken.extend({
    tableName: 'accesstokens',

    emitChange: function emitChange(event, options) {
        const eventToTrigger = 'token' + '.' + event;
        ghostBookshelf.Model.prototype.emitChange.bind(this)(this, eventToTrigger, options);
    },

    onCreated: function onCreated(model, attrs, options) {
        ghostBookshelf.Model.prototype.onCreated.apply(this, arguments);
        model.emitChange('added', options);
    }
});

Accesstokens = ghostBookshelf.Collection.extend({
    model: Accesstoken
});

module.exports = {
    Accesstoken: ghostBookshelf.model('Accesstoken', Accesstoken),
    Accesstokens: ghostBookshelf.collection('Accesstokens', Accesstokens)
};


<|start_filename|>core/server/lib/members/static/auth/components/PasswordInput.js<|end_filename|>
import FormInput from './FormInput';
import { IconLock } from './icons';

export default ({value, error, children, onInput, className}) => (
    <FormInput
        type="password"
        name="password"
        label="Password"
        value={value}
        error={error}
        icon={IconLock}
        placeholder="Password..."
        required={true}
        className={className}
        onInput={onInput}>
        { children }
    </FormInput>
);


<|start_filename|>core/server/data/db/backup.js<|end_filename|>
// # Backup Database
// Provides for backing up the database before making potentially destructive changes
var fs = require('fs-extra'),
    path = require('path'),
    Promise = require('bluebird'),
    config = require('../../config'),
    common = require('../../lib/common'),
    urlService = require('../../services/url'),
    exporter = require('../exporter'),

    writeExportFile,
    backup;

writeExportFile = function writeExportFile(exportResult) {
    var filename = path.resolve(urlService.utils.urlJoin(config.get('paths').contentPath, 'data', exportResult.filename));

    return fs.writeFile(filename, JSON.stringify(exportResult.data)).return(filename);
};

/**
 * ## Backup
 * does an export, and stores this in a local file
 * @returns {Promise<*>}
 */
backup = function backup(options) {
    common.logging.info('Creating database backup');
    options = options || {};

    var props = {
        data: exporter.doExport(options),
        filename: exporter.fileName(options)
    };

    return Promise.props(props)
        .then(writeExportFile)
        .then(function successMessage(filename) {
            common.logging.info('Database backup written to: ' + filename);
            return filename;
        });
};

module.exports = backup;


<|start_filename|>core/server/web/shared/middlewares/admin-redirects.js<|end_filename|>
const express = require('express');
const urlService = require('../../../services/url');

const adminRedirect = (path) => {
    return function doRedirect(req, res) {
        return urlService.utils.redirectToAdmin(301, res, path);
    };
};

module.exports = function adminRedirects() {
    const router = express.Router();
    // Admin redirects - register redirect as route
    // TODO: this should be middleware!
    router.get(/^\/(logout|signout)\/$/, adminRedirect('#/signout/'));
    router.get(/^\/signup\/$/, adminRedirect('#/signup/'));
    // redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
    router.get(/^\/((ghost-admin|admin|dashboard|signin|login)\/?)$/, adminRedirect('/'));

    return router;
};


<|start_filename|>core/server/api/v2/utils/serializers/output/subscribers.js<|end_filename|>
const common = require('../../../../../lib/common');
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:output:subscribers');

module.exports = {
    browse(models, apiConfig, frame) {
        debug('browse');

        frame.response = {
            subscribers: models.data.map(model => model.toJSON(frame.options)),
            meta: models.meta
        };
    },

    read(models, apiConfig, frame) {
        debug('read');

        if (!models) {
            return Promise.reject(new common.errors.NotFoundError({
                message: common.i18n.t('errors.api.subscribers.subscriberNotFound')
            }));
        }

        frame.response = {
            subscribers: [models.toJSON(frame.options)]
        };
    },

    add(models, apiConfig, frame) {
        debug('add');

        frame.response = {
            subscribers: [models.toJSON(frame.options)]
        };
    },

    edit(models, apiConfig, frame) {
        debug('edit');

        frame.response = {
            subscribers: [models.toJSON(frame.options)]
        };
    },

    destroy(models, apiConfig, frame) {
        frame.response = models;
    },

    exportCSV(models, apiConfig, frame) {
        debug('exportCSV');

        function formatCSV(data) {
            let fields = ['id', 'email', 'created_at', 'deleted_at'],
                csv = `${fields.join(',')}\r\n`,
                subscriber,
                field,
                j,
                i;

            for (j = 0; j < data.length; j = j + 1) {
                subscriber = data[j];

                for (i = 0; i < fields.length; i = i + 1) {
                    field = fields[i];
                    csv += subscriber[field] !== null ? subscriber[field] : '';
                    if (i !== fields.length - 1) {
                        csv += ',';
                    }
                }
                csv += '\r\n';
            }

            return csv;
        }

        frame.response = formatCSV(models.toJSON(frame.options), frame.options);
    },

    importCSV(models, apiConfig, frame) {
        debug('importCSV');

        frame.response = models;
    }
};


<|start_filename|>core/server/web/shared/middlewares/image/index.js<|end_filename|>
module.exports = {
    get normalize() {
        return require('./normalize');
    },
    get handleImageSizes() {
        return require('./handle-image-sizes');
    }
};
